blob: d4040b5ebf60baed169b68da56481281135e8bd8 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Tracks lifetimes of objects created by other components.
#include "common/shared_object_tracker.h"
#include <map>
#include "base/memory/singleton.h"
#include "base/synchronization/lock.h"
#include "common/alog.h"
namespace arc {
class TrackerStorage {
public:
static TrackerStorage* GetInstance();
int Register(SharedObjectDestroyFunc destroy_func, void* param);
void IncRef(int handle);
bool DecRef(int handle);
private:
struct Object {
Object(SharedObjectDestroyFunc destroy_func, void* param);
~Object();
void IncRef();
bool DecRef();
private:
Object(const Object&);
void operator=(const Object&);
SharedObjectDestroyFunc destroy_func_;
void* param_;
int ref_count_;
};
typedef std::map<int, Object*> ObjectMap;
TrackerStorage() : handle_gen_(0) {}
~TrackerStorage() {}
Object* FindObjectLocked(int handle);
base::Lock mu_;
ObjectMap objects_;
int handle_gen_;
friend struct DefaultSingletonTraits<TrackerStorage>;
};
TrackerStorage::Object::Object(
SharedObjectDestroyFunc destroy_func, void* param)
: destroy_func_(destroy_func), param_(param), ref_count_(1) {
ALOG_ASSERT(destroy_func);
}
TrackerStorage::Object::~Object() {
destroy_func_(param_);
}
void TrackerStorage::Object::IncRef() {
ref_count_++;
}
bool TrackerStorage::Object::DecRef() {
ref_count_--;
return (ref_count_ == 0);
}
TrackerStorage* TrackerStorage::GetInstance() {
return Singleton<TrackerStorage,
LeakySingletonTraits<TrackerStorage> >::get();
}
int TrackerStorage::Register(
SharedObjectDestroyFunc destroy_func, void* param) {
base::AutoLock lock(mu_);
LOG_ALWAYS_FATAL_IF(handle_gen_ == INT_MAX);
int handle = ++handle_gen_;
Object* obj = new Object(destroy_func, param);
objects_[handle] = obj;
return handle;
}
void TrackerStorage::IncRef(int handle) {
base::AutoLock lock(mu_);
Object* obj = FindObjectLocked(handle);
if (!obj) {
ALOG_ASSERT(false);
return;
}
obj->IncRef();
}
bool TrackerStorage::DecRef(int handle) {
if (!handle)
return false;
bool is_dead;
Object* obj;
{
base::AutoLock lock(mu_);
obj = FindObjectLocked(handle);
if (!obj) {
ALOG_ASSERT(false);
return false;
}
is_dead = obj->DecRef();
}
if (is_dead) {
objects_.erase(handle);
delete obj;
}
return is_dead;
}
TrackerStorage::Object* TrackerStorage::FindObjectLocked(int handle) {
ObjectMap::iterator it = objects_.find(handle);
return (it != objects_.end() ? it->second : NULL);
}
int SharedObjectTracker::Register(
SharedObjectDestroyFunc destroy_func, void* param) {
return TrackerStorage::GetInstance()->Register(destroy_func, param);
}
void SharedObjectTracker::IncRef(int handle) {
TrackerStorage::GetInstance()->IncRef(handle);
}
bool SharedObjectTracker::DecRef(int handle) {
return TrackerStorage::GetInstance()->DecRef(handle);
}
} // namespace arc