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