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