LogCabin
|
00001 /* Copyright (c) 2011-2012 Stanford University 00002 * 00003 * Permission to use, copy, modify, and distribute this software for any purpose 00004 * with or without fee is hereby granted, provided that the above copyright 00005 * notice and this permission notice appear in all copies. 00006 * 00007 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES 00008 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 00009 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR ANY 00010 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 00011 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 00012 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 00013 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00014 */ 00015 00016 #include <mutex> 00017 #include <unordered_map> 00018 00019 #include "Core/ThreadId.h" 00020 #include "Core/StringUtil.h" 00021 00022 namespace LogCabin { 00023 namespace Core { 00024 namespace ThreadId { 00025 namespace Internal { 00026 00027 /** 00028 * Thread-specific data holds the identifier for each thread. It starts off 00029 * zero, but is set to a non-zero unique value the first time it is accessed. 00030 */ 00031 __thread uint64_t id = 0; 00032 00033 /** 00034 * Used to serialize access to #nextId. 00035 */ 00036 std::mutex mutex; 00037 00038 /** 00039 * The next thread identifier that has not already been used. 00040 */ 00041 uint64_t nextId = 1; 00042 00043 /** 00044 * A map from thread ID to thread name. 00045 * Not all threads may be present in this map; only those that have had their 00046 * name set will be found here. 00047 */ 00048 std::unordered_map<uint64_t, std::string> threadNames; 00049 00050 /** 00051 * Pick a unique value to use as the thread identifier for the current 00052 * thread. This value is saved in the thread-specific variable #id. 00053 */ 00054 void 00055 assign() 00056 { 00057 std::lock_guard<std::mutex> lockGuard(mutex); 00058 id = nextId; 00059 ++nextId; 00060 } 00061 00062 } // namespace LogCabin::Core::ThreadId::Internal 00063 00064 /** 00065 * Return a unique identifier associated with this thread. The 00066 * return value has two properties: 00067 * - It will never be zero. 00068 * - It will be unique for this thread (i.e., no other thread has ever 00069 * been returned this value or ever will be returned this value) 00070 */ 00071 uint64_t 00072 getId() 00073 { 00074 if (Internal::id == 0) 00075 Internal::assign(); 00076 return Internal::id; 00077 } 00078 00079 void 00080 setName(const std::string& name) 00081 { 00082 // get the thread ID before locking to avoid deadlock 00083 uint64_t id = getId(); 00084 std::lock_guard<std::mutex> lockGuard(Internal::mutex); 00085 if (name.empty()) 00086 Internal::threadNames.erase(id); 00087 else 00088 Internal::threadNames[id] = name; 00089 } 00090 00091 std::string 00092 getName() 00093 { 00094 // get the thread ID before locking to avoid deadlock 00095 uint64_t id = getId(); 00096 std::lock_guard<std::mutex> lockGuard(Internal::mutex); 00097 auto it = Internal::threadNames.find(id); 00098 if (it == Internal::threadNames.end()) 00099 return StringUtil::format("thread %lu", id); 00100 else 00101 return it->second; 00102 } 00103 00104 } // namespace LogCabin::Core::ThreadId 00105 } // namespace LogCabin::Core 00106 } // namespace LogCabin