blob: c1f7684687d7e8f59cf6a5099f5953503552197a [file] [log] [blame]
// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/base/c_val.h"
#include <sstream>
namespace base {
CValManager* CValManager::GetInstance() {
return base::Singleton<
CValManager, base::StaticMemorySingletonTraits<CValManager> >::get();
}
CValManager::CValManager() : value_lock_refptr_(new RefCountedThreadSafeLock) {
// Allocate these dynamically since CValManager may live across DLL boundaries
// and so this allows its size to be more consistent (and avoids compiler
// warnings on some platforms).
registered_vars_ = new NameVarMap();
#if defined(ENABLE_DEBUG_C_VAL)
on_changed_hook_set_ = new base::hash_set<OnChangedHook*>();
#endif // ENABLE_DEBUG_C_VAL
}
CValManager::~CValManager() {
// Lock the value lock prior to notifying the surviving CVals that the manager
// has been destroyed. This ensures that they will not attempt to make calls
// into the manager during destruction.
base::AutoLock auto_lock(value_lock_refptr_->GetLock());
for (NameVarMap::iterator iter = registered_vars_->begin();
iter != registered_vars_->end(); ++iter) {
iter->second->OnManagerDestroyed();
}
#if defined(ENABLE_DEBUG_C_VAL)
delete on_changed_hook_set_;
#endif // ENABLE_DEBUG_C_VAL
delete registered_vars_;
}
void CValManager::RegisterCVal(
const CValDetail::CValBase* cval,
scoped_refptr<base::RefCountedThreadSafeLock>* value_lock) {
base::AutoLock auto_lock(cvals_lock_);
// CVals cannot share name. If this assert is triggered, we are trying to
// register more than one CVal with the same name, which this system is
// not designed to handle.
DCHECK(registered_vars_->find(cval->GetName()) == registered_vars_->end());
(*registered_vars_)[cval->GetName()] = cval;
*value_lock = value_lock_refptr_;
}
void CValManager::UnregisterCVal(const CValDetail::CValBase* cval) {
base::AutoLock auto_lock(cvals_lock_);
NameVarMap::iterator found = registered_vars_->find(cval->GetName());
DCHECK(found != registered_vars_->end());
if (found != registered_vars_->end()) {
registered_vars_->erase(found);
}
}
#if defined(ENABLE_DEBUG_C_VAL)
void CValManager::PushValueChangedEvent(const CValDetail::CValBase* cval,
const CValGenericValue& value) {
base::AutoLock auto_lock(hooks_lock_);
// Iterate through the hooks sending each of them the value changed event.
for (OnChangeHookSet::iterator iter = on_changed_hook_set_->begin();
iter != on_changed_hook_set_->end(); ++iter) {
(*iter)->OnValueChanged(cval->GetName(), value);
}
}
CValManager::OnChangedHook::OnChangedHook() {
CValManager* cvm = CValManager::GetInstance();
base::AutoLock auto_lock(cvm->hooks_lock_);
// Register this hook with the CValManager
bool was_inserted ALLOW_UNUSED_TYPE =
cvm->on_changed_hook_set_->insert(this).second;
DCHECK(was_inserted);
}
CValManager::OnChangedHook::~OnChangedHook() {
CValManager* cvm = CValManager::GetInstance();
base::AutoLock auto_lock(cvm->hooks_lock_);
// Deregister this hook with the CValManager
size_t values_erased ALLOW_UNUSED_TYPE =
cvm->on_changed_hook_set_->erase(this);
DCHECK_EQ(values_erased, 1);
}
#endif // ENABLE_DEBUG_C_VAL
std::set<std::string> CValManager::GetOrderedCValNames() {
std::set<std::string> ret;
base::AutoLock auto_lock(cvals_lock_);
// Return all registered CVal names, as an std::set to show they are sorted.
for (NameVarMap::const_iterator iter = registered_vars_->begin();
iter != registered_vars_->end(); ++iter) {
ret.insert(iter->first);
}
return ret;
}
Optional<std::string> CValManager::GetCValStringValue(const std::string& name,
bool pretty) {
base::AutoLock auto_lock(cvals_lock_);
// Return the value of a CVal, if it exists. If it does not exist,
// indicate that it does not exist.
NameVarMap::const_iterator found = registered_vars_->find(name);
if (found == registered_vars_->end()) {
return nullopt;
} else {
return (pretty ? found->second->GetValueAsPrettyString()
: found->second->GetValueAsString());
}
}
Optional<std::string> CValManager::GetValueAsString(const std::string& name) {
return GetCValStringValue(name, false);
}
Optional<std::string> CValManager::GetValueAsPrettyString(
const std::string& name) {
return GetCValStringValue(name, true);
}
} // namespace base