#include "libcef/common/value_base.h"
CefValueController::CefValueController()
: owner_value_(nullptr), owner_object_(nullptr) {}
CefValueController::~CefValueController() {
DCHECK(!owner_value_ && !owner_object_);
DCHECK(reference_map_.empty());
DCHECK(dependency_map_.empty());
}
void CefValueController::SetOwner(void* value, Object* object) {
DCHECK(value && object);
DCHECK(locked());
DCHECK(!owner_value_ && !owner_object_);
owner_value_ = value;
owner_object_ = object;
}
void CefValueController::AddReference(void* value, Object* object) {
DCHECK(value && object);
DCHECK(locked());
DCHECK(owner_value_);
DCHECK(reference_map_.find(value) == reference_map_.end());
DCHECK(value != owner_value_);
reference_map_.insert(std::make_pair(value, object));
}
void CefValueController::Remove(void* value, bool notify_object) {
DCHECK(value);
DCHECK(locked());
DCHECK(owner_value_);
if (value == owner_value_) {
DCHECK(!notify_object);
owner_value_ = nullptr;
owner_object_ = nullptr;
if (reference_map_.size() > 0) {
ReferenceMap::iterator it = reference_map_.begin();
for (; it != reference_map_.end(); ++it)
it->second->OnControlRemoved();
reference_map_.clear();
}
dependency_map_.clear();
} else {
ReferenceMap::iterator it = reference_map_.find(value);
if (it != reference_map_.end()) {
if (notify_object)
it->second->OnControlRemoved();
reference_map_.erase(it);
}
}
}
CefValueController::Object* CefValueController::Get(void* value) {
DCHECK(value);
DCHECK(locked());
if (value == owner_value_) {
return owner_object_;
} else {
ReferenceMap::iterator it = reference_map_.find(value);
if (it != reference_map_.end())
return it->second;
return nullptr;
}
}
void CefValueController::AddDependency(void* parent, void* child) {
DCHECK(parent && child && parent != child);
DCHECK(locked());
DependencyMap::iterator it = dependency_map_.find(parent);
if (it == dependency_map_.end()) {
DependencySet set;
set.insert(child);
dependency_map_.insert(std::make_pair(parent, set));
} else if (it->second.find(child) == it->second.end()) {
it->second.insert(child);
}
}
void CefValueController::RemoveDependencies(void* value) {
DCHECK(value);
DCHECK(locked());
if (dependency_map_.empty())
return;
DependencyMap::iterator it_dependency = dependency_map_.find(value);
if (it_dependency == dependency_map_.end())
return;
DependencySet remove_set = it_dependency->second;
dependency_map_.erase(it_dependency);
DependencySet::iterator it_value;
ReferenceMap::iterator it_reference;
while (remove_set.size() > 0) {
it_value = remove_set.begin();
value = *it_value;
remove_set.erase(it_value);
it_dependency = dependency_map_.find(value);
if (it_dependency != dependency_map_.end()) {
remove_set.insert(it_dependency->second.begin(),
it_dependency->second.end());
dependency_map_.erase(it_dependency);
}
it_reference = reference_map_.find(value);
if (it_reference != reference_map_.end()) {
it_reference->second->OnControlRemoved();
reference_map_.erase(it_reference);
}
}
}
void CefValueController::TakeFrom(CefValueController* other) {
DCHECK(other);
DCHECK(locked());
DCHECK(other->locked());
if (!other->reference_map_.empty()) {
ReferenceMap::iterator it = other->reference_map_.begin();
for (; it != other->reference_map_.end(); ++it) {
DCHECK(reference_map_.find(it->first) == reference_map_.end());
reference_map_.insert(std::make_pair(it->first, it->second));
}
other->reference_map_.clear();
}
if (!other->dependency_map_.empty()) {
DependencyMap::iterator it_other = other->dependency_map_.begin();
for (; it_other != other->dependency_map_.end(); ++it_other) {
DependencyMap::iterator it_me = dependency_map_.find(it_other->first);
if (it_me == dependency_map_.end()) {
dependency_map_.insert(
std::make_pair(it_other->first, it_other->second));
} else {
DependencySet::iterator it_other_set = it_other->second.begin();
for (; it_other_set != it_other->second.end(); ++it_other_set) {
if (it_me->second.find(*it_other_set) == it_me->second.end())
it_me->second.insert(*it_other_set);
}
}
}
}
}
void CefValueController::Swap(void* old_value, void* new_value) {
DCHECK(old_value && new_value && old_value != new_value);
DCHECK(locked());
if (owner_value_ == old_value)
owner_value_ = new_value;
if (!reference_map_.empty()) {
ReferenceMap::iterator it = reference_map_.find(old_value);
if (it != reference_map_.end()) {
DCHECK(reference_map_.find(new_value) == reference_map_.end());
reference_map_.insert(std::make_pair(new_value, it->second));
reference_map_.erase(it);
}
}
if (!dependency_map_.empty()) {
DependencyMap::iterator it = dependency_map_.find(old_value);
if (it != dependency_map_.end()) {
dependency_map_.insert(std::make_pair(new_value, it->second));
dependency_map_.erase(it);
}
it = dependency_map_.begin();
for (; it != dependency_map_.end(); ++it) {
DependencySet::iterator dit = it->second.find(old_value);
if (dit != it->second.end()) {
it->second.insert(new_value);
it->second.erase(dit);
}
}
}
}