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 14 namespace base { 15 namespace { 16 17 static const char kDefaultName[] = ""; 18 static std::string* g_default_name; 19 20 } 21 ThreadIdNameManager()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 ~ThreadIdNameManager()31ThreadIdNameManager::~ThreadIdNameManager() { 32 } 33 GetInstance()34ThreadIdNameManager* ThreadIdNameManager::GetInstance() { 35 return Singleton<ThreadIdNameManager, 36 LeakySingletonTraits<ThreadIdNameManager> >::get(); 37 } 38 GetDefaultInternedString()39const char* ThreadIdNameManager::GetDefaultInternedString() { 40 return g_default_name->c_str(); 41 } 42 RegisterThread(PlatformThreadHandle::Handle handle,PlatformThreadId id)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 SetName(PlatformThreadId id,const char * name)51void ThreadIdNameManager::SetName(PlatformThreadId id, const char* name) { 52 std::string str_name(name); 53 54 AutoLock locked(lock_); 55 NameToInternedNameMap::iterator iter = name_to_interned_name_.find(str_name); 56 std::string* leaked_str = NULL; 57 if (iter != name_to_interned_name_.end()) { 58 leaked_str = iter->second; 59 } else { 60 leaked_str = new std::string(str_name); 61 name_to_interned_name_[str_name] = leaked_str; 62 } 63 64 ThreadIdToHandleMap::iterator id_to_handle_iter = 65 thread_id_to_handle_.find(id); 66 67 // The main thread of a process will not be created as a Thread object which 68 // means there is no PlatformThreadHandler registered. 69 if (id_to_handle_iter == thread_id_to_handle_.end()) { 70 main_process_name_ = leaked_str; 71 main_process_id_ = id; 72 return; 73 } 74 thread_handle_to_interned_name_[id_to_handle_iter->second] = leaked_str; 75 } 76 GetName(PlatformThreadId id)77const char* ThreadIdNameManager::GetName(PlatformThreadId id) { 78 AutoLock locked(lock_); 79 80 if (id == main_process_id_) 81 return main_process_name_->c_str(); 82 83 ThreadIdToHandleMap::iterator id_to_handle_iter = 84 thread_id_to_handle_.find(id); 85 if (id_to_handle_iter == thread_id_to_handle_.end()) 86 return name_to_interned_name_[kDefaultName]->c_str(); 87 88 ThreadHandleToInternedNameMap::iterator handle_to_name_iter = 89 thread_handle_to_interned_name_.find(id_to_handle_iter->second); 90 return handle_to_name_iter->second->c_str(); 91 } 92 RemoveName(PlatformThreadHandle::Handle handle,PlatformThreadId id)93void ThreadIdNameManager::RemoveName(PlatformThreadHandle::Handle handle, 94 PlatformThreadId id) { 95 AutoLock locked(lock_); 96 ThreadHandleToInternedNameMap::iterator handle_to_name_iter = 97 thread_handle_to_interned_name_.find(handle); 98 99 DCHECK(handle_to_name_iter != thread_handle_to_interned_name_.end()); 100 thread_handle_to_interned_name_.erase(handle_to_name_iter); 101 102 ThreadIdToHandleMap::iterator id_to_handle_iter = 103 thread_id_to_handle_.find(id); 104 DCHECK((id_to_handle_iter!= thread_id_to_handle_.end())); 105 // The given |id| may have been re-used by the system. Make sure the 106 // mapping points to the provided |handle| before removal. 107 if (id_to_handle_iter->second != handle) 108 return; 109 110 thread_id_to_handle_.erase(id_to_handle_iter); 111 } 112 113 } // namespace base 114