1 //  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 //
6 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
9 
10 #pragma once
11 
12 #include <atomic>
13 #include <functional>
14 #include <memory>
15 #include <unordered_map>
16 #include <vector>
17 
18 #include "util/autovector.h"
19 #include "port/port.h"
20 
21 namespace ROCKSDB_NAMESPACE {
22 
23 // Cleanup function that will be called for a stored thread local
24 // pointer (if not NULL) when one of the following happens:
25 // (1) a thread terminates
26 // (2) a ThreadLocalPtr is destroyed
27 //
28 // Warning: this function is called while holding a global mutex. The same mutex
29 // is used (at least in some cases) by most methods of ThreadLocalPtr, and it's
30 // shared across all instances of ThreadLocalPtr. Thereforere extra care
31 // is needed to avoid deadlocks. In particular, the handler shouldn't lock any
32 // mutexes and shouldn't call any methods of any ThreadLocalPtr instances,
33 // unless you know what you're doing.
34 typedef void (*UnrefHandler)(void* ptr);
35 
36 // ThreadLocalPtr stores only values of pointer type.  Different from
37 // the usual thread-local-storage, ThreadLocalPtr has the ability to
38 // distinguish data coming from different threads and different
39 // ThreadLocalPtr instances.  For example, if a regular thread_local
40 // variable A is declared in DBImpl, two DBImpl objects would share
41 // the same A.  However, a ThreadLocalPtr that is defined under the
42 // scope of DBImpl can avoid such confliction.  As a result, its memory
43 // usage would be O(# of threads * # of ThreadLocalPtr instances).
44 class ThreadLocalPtr {
45  public:
46   explicit ThreadLocalPtr(UnrefHandler handler = nullptr);
47 
48   ThreadLocalPtr(const ThreadLocalPtr&) = delete;
49   ThreadLocalPtr& operator=(const ThreadLocalPtr&) = delete;
50 
51   ~ThreadLocalPtr();
52 
53   // Return the current pointer stored in thread local
54   void* Get() const;
55 
56   // Set a new pointer value to the thread local storage.
57   void Reset(void* ptr);
58 
59   // Atomically swap the supplied ptr and return the previous value
60   void* Swap(void* ptr);
61 
62   // Atomically compare the stored value with expected. Set the new
63   // pointer value to thread local only if the comparison is true.
64   // Otherwise, expected returns the stored value.
65   // Return true on success, false on failure
66   bool CompareAndSwap(void* ptr, void*& expected);
67 
68   // Reset all thread local data to replacement, and return non-nullptr
69   // data for all existing threads
70   void Scrape(autovector<void*>* ptrs, void* const replacement);
71 
72   typedef std::function<void(void*, void*)> FoldFunc;
73   // Update res by applying func on each thread-local value. Holds a lock that
74   // prevents unref handler from running during this call, but clients must
75   // still provide external synchronization since the owning thread can
76   // access the values without internal locking, e.g., via Get() and Reset().
77   void Fold(FoldFunc func, void* res);
78 
79   // Add here for testing
80   // Return the next available Id without claiming it
81   static uint32_t TEST_PeekId();
82 
83   // Initialize the static singletons of the ThreadLocalPtr.
84   //
85   // If this function is not called, then the singletons will be
86   // automatically initialized when they are used.
87   //
88   // Calling this function twice or after the singletons have been
89   // initialized will be no-op.
90   static void InitSingletons();
91 
92   class StaticMeta;
93 
94 private:
95 
96   static StaticMeta* Instance();
97 
98   const uint32_t id_;
99 };
100 
101 }  // namespace ROCKSDB_NAMESPACE
102