1 // Copyright 2011 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // WARNING: Thread local storage is a bit tricky to get right. Please make sure 6 // that this is really the proper solution for what you're trying to achieve. 7 // Don't prematurely optimize, most likely you can just use a Lock. 8 9 #ifndef BASE_THREADING_THREAD_LOCAL_H_ 10 #define BASE_THREADING_THREAD_LOCAL_H_ 11 12 #include <memory> 13 14 #include "base/dcheck_is_on.h" 15 #include "base/memory/ptr_util.h" 16 #include "base/threading/thread_local_internal.h" 17 #include "base/threading/thread_local_storage.h" 18 19 namespace base { 20 21 // `thread_local` is only allowed for trivially-destructible types (see 22 // //styleguide/c++/c++.md#thread_local-variables). This class provides 23 // thread-scoped management of non-trivially-destructible types. Pointers handed 24 // to it are owned and automatically deleted during their associated thread's 25 // exit phase (or when replaced if Set() is invoked multiple times on the same 26 // thread). 27 // 28 // The ThreadLocalOwnedPointer instance itself can only be destroyed when no 29 // threads, other than the one it is destroyed on, have remaining state set in 30 // it. Typically this means that ThreadLocalOwnedPointer instances are held in 31 // static storage or at the very least only recycled in the single-threaded 32 // phase between tests in the same process. 33 #if DCHECK_IS_ON() 34 template <typename T> 35 using ThreadLocalOwnedPointer = internal::CheckedThreadLocalOwnedPointer<T>; 36 #else // DCHECK_IS_ON() 37 template <typename T> 38 class ThreadLocalOwnedPointer { 39 public: 40 ThreadLocalOwnedPointer() = default; 41 42 ThreadLocalOwnedPointer(const ThreadLocalOwnedPointer&) = delete; 43 ThreadLocalOwnedPointer& operator=(const ThreadLocalOwnedPointer&) = delete; 44 45 ~ThreadLocalOwnedPointer() { 46 // Assume that this thread is the only one with potential state left. This 47 // is verified in ~CheckedThreadLocalOwnedPointer(). 48 Set(nullptr); 49 } 50 51 T* Get() const { return static_cast<T*>(slot_.Get()); } 52 53 // Sets a new value, returns the old. 54 std::unique_ptr<T> Set(std::unique_ptr<T> ptr) { 55 auto existing = WrapUnique(Get()); 56 slot_.Set(const_cast<void*>(static_cast<const void*>(ptr.release()))); 57 return existing; 58 } 59 60 T& operator*() { return *Get(); } 61 62 private: 63 static void DeleteTlsPtr(void* ptr) { delete static_cast<T*>(ptr); } 64 65 ThreadLocalStorage::Slot slot_{&DeleteTlsPtr}; 66 }; 67 #endif // DCHECK_IS_ON() 68 69 } // namespace base 70 71 #endif // BASE_THREADING_THREAD_LOCAL_H_ 72