michael@0: // Copyright (c) 2012 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #include "base/threading/thread_id_name_manager.h" michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "base/logging.h" michael@0: #include "base/memory/singleton.h" michael@0: #include "base/strings/string_util.h" michael@0: michael@0: namespace base { michael@0: namespace { michael@0: michael@0: static const char kDefaultName[] = ""; michael@0: static std::string* g_default_name; michael@0: michael@0: } michael@0: michael@0: ThreadIdNameManager::ThreadIdNameManager() michael@0: : main_process_name_(NULL), michael@0: main_process_id_(kInvalidThreadId) { michael@0: g_default_name = new std::string(kDefaultName); michael@0: michael@0: AutoLock locked(lock_); michael@0: name_to_interned_name_[kDefaultName] = g_default_name; michael@0: } michael@0: michael@0: ThreadIdNameManager::~ThreadIdNameManager() { michael@0: } michael@0: michael@0: ThreadIdNameManager* ThreadIdNameManager::GetInstance() { michael@0: return Singleton >::get(); michael@0: } michael@0: michael@0: const char* ThreadIdNameManager::GetDefaultInternedString() { michael@0: return g_default_name->c_str(); michael@0: } michael@0: michael@0: void ThreadIdNameManager::RegisterThread(PlatformThreadHandle::Handle handle, michael@0: PlatformThreadId id) { michael@0: AutoLock locked(lock_); michael@0: thread_id_to_handle_[id] = handle; michael@0: thread_handle_to_interned_name_[handle] = michael@0: name_to_interned_name_[kDefaultName]; michael@0: } michael@0: michael@0: void ThreadIdNameManager::SetName(PlatformThreadId id, const char* name) { michael@0: std::string str_name(name); michael@0: michael@0: AutoLock locked(lock_); michael@0: NameToInternedNameMap::iterator iter = name_to_interned_name_.find(str_name); michael@0: std::string* leaked_str = NULL; michael@0: if (iter != name_to_interned_name_.end()) { michael@0: leaked_str = iter->second; michael@0: } else { michael@0: leaked_str = new std::string(str_name); michael@0: name_to_interned_name_[str_name] = leaked_str; michael@0: } michael@0: michael@0: ThreadIdToHandleMap::iterator id_to_handle_iter = michael@0: thread_id_to_handle_.find(id); michael@0: michael@0: // The main thread of a process will not be created as a Thread object which michael@0: // means there is no PlatformThreadHandler registered. michael@0: if (id_to_handle_iter == thread_id_to_handle_.end()) { michael@0: main_process_name_ = leaked_str; michael@0: main_process_id_ = id; michael@0: return; michael@0: } michael@0: thread_handle_to_interned_name_[id_to_handle_iter->second] = leaked_str; michael@0: } michael@0: michael@0: const char* ThreadIdNameManager::GetName(PlatformThreadId id) { michael@0: AutoLock locked(lock_); michael@0: michael@0: if (id == main_process_id_) michael@0: return main_process_name_->c_str(); michael@0: michael@0: ThreadIdToHandleMap::iterator id_to_handle_iter = michael@0: thread_id_to_handle_.find(id); michael@0: if (id_to_handle_iter == thread_id_to_handle_.end()) michael@0: return name_to_interned_name_[kDefaultName]->c_str(); michael@0: michael@0: ThreadHandleToInternedNameMap::iterator handle_to_name_iter = michael@0: thread_handle_to_interned_name_.find(id_to_handle_iter->second); michael@0: return handle_to_name_iter->second->c_str(); michael@0: } michael@0: michael@0: void ThreadIdNameManager::RemoveName(PlatformThreadHandle::Handle handle, michael@0: PlatformThreadId id) { michael@0: AutoLock locked(lock_); michael@0: ThreadHandleToInternedNameMap::iterator handle_to_name_iter = michael@0: thread_handle_to_interned_name_.find(handle); michael@0: michael@0: DCHECK(handle_to_name_iter != thread_handle_to_interned_name_.end()); michael@0: thread_handle_to_interned_name_.erase(handle_to_name_iter); michael@0: michael@0: ThreadIdToHandleMap::iterator id_to_handle_iter = michael@0: thread_id_to_handle_.find(id); michael@0: DCHECK((id_to_handle_iter!= thread_id_to_handle_.end())); michael@0: // The given |id| may have been re-used by the system. Make sure the michael@0: // mapping points to the provided |handle| before removal. michael@0: if (id_to_handle_iter->second != handle) michael@0: return; michael@0: michael@0: thread_id_to_handle_.erase(id_to_handle_iter); michael@0: } michael@0: michael@0: } // namespace base