1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/threading/thread_id_name_manager.h" 6 7#include <stdlib.h> 8#include <string.h> 9 10#include "base/logging.h" 11#include "base/memory/singleton.h" 12#include "base/strings/string_util.h" 13 14namespace base { 15namespace { 16 17static const char kDefaultName[] = ""; 18static std::string* g_default_name; 19 20} 21 22ThreadIdNameManager::ThreadIdNameManager() 23 : main_process_name_(NULL), 24 main_process_id_(kInvalidThreadId) { 25 g_default_name = new std::string(kDefaultName); 26 27 AutoLock locked(lock_); 28 name_to_interned_name_[kDefaultName] = g_default_name; 29} 30 31ThreadIdNameManager::~ThreadIdNameManager() { 32} 33 34ThreadIdNameManager* ThreadIdNameManager::GetInstance() { 35 return Singleton<ThreadIdNameManager, 36 LeakySingletonTraits<ThreadIdNameManager> >::get(); 37} 38 39const char* ThreadIdNameManager::GetDefaultInternedString() { 40 return g_default_name->c_str(); 41} 42 43void ThreadIdNameManager::RegisterThread(PlatformThreadHandle::Handle handle, 44 PlatformThreadId id) { 45 AutoLock locked(lock_); 46 thread_id_to_handle_[id] = handle; 47 thread_handle_to_interned_name_[handle] = 48 name_to_interned_name_[kDefaultName]; 49} 50 51void ThreadIdNameManager::SetName(PlatformThreadId id, 52 const std::string& name) { 53 AutoLock locked(lock_); 54 NameToInternedNameMap::iterator iter = name_to_interned_name_.find(name); 55 std::string* leaked_str = NULL; 56 if (iter != name_to_interned_name_.end()) { 57 leaked_str = iter->second; 58 } else { 59 leaked_str = new std::string(name); 60 name_to_interned_name_[name] = leaked_str; 61 } 62 63 ThreadIdToHandleMap::iterator id_to_handle_iter = 64 thread_id_to_handle_.find(id); 65 66 // The main thread of a process will not be created as a Thread object which 67 // means there is no PlatformThreadHandler registered. 68 if (id_to_handle_iter == thread_id_to_handle_.end()) { 69 main_process_name_ = leaked_str; 70 main_process_id_ = id; 71 return; 72 } 73 thread_handle_to_interned_name_[id_to_handle_iter->second] = leaked_str; 74} 75 76const char* ThreadIdNameManager::GetName(PlatformThreadId id) { 77 AutoLock locked(lock_); 78 79 if (id == main_process_id_) 80 return main_process_name_->c_str(); 81 82 ThreadIdToHandleMap::iterator id_to_handle_iter = 83 thread_id_to_handle_.find(id); 84 if (id_to_handle_iter == thread_id_to_handle_.end()) 85 return name_to_interned_name_[kDefaultName]->c_str(); 86 87 ThreadHandleToInternedNameMap::iterator handle_to_name_iter = 88 thread_handle_to_interned_name_.find(id_to_handle_iter->second); 89 return handle_to_name_iter->second->c_str(); 90} 91 92void ThreadIdNameManager::RemoveName(PlatformThreadHandle::Handle handle, 93 PlatformThreadId id) { 94 AutoLock locked(lock_); 95 ThreadHandleToInternedNameMap::iterator handle_to_name_iter = 96 thread_handle_to_interned_name_.find(handle); 97 98 DCHECK(handle_to_name_iter != thread_handle_to_interned_name_.end()); 99 thread_handle_to_interned_name_.erase(handle_to_name_iter); 100 101 ThreadIdToHandleMap::iterator id_to_handle_iter = 102 thread_id_to_handle_.find(id); 103 DCHECK((id_to_handle_iter!= thread_id_to_handle_.end())); 104 // The given |id| may have been re-used by the system. Make sure the 105 // mapping points to the provided |handle| before removal. 106 if (id_to_handle_iter->second != handle) 107 return; 108 109 thread_id_to_handle_.erase(id_to_handle_iter); 110} 111 112} // namespace base 113