LogCabin
Core/ThreadId.cc
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines