1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file. 4*635a8641SAndroid Build Coastguard Worker 5*635a8641SAndroid Build Coastguard Worker // WARNING: Thread local storage is a bit tricky to get right. Please make sure 6*635a8641SAndroid Build Coastguard Worker // that this is really the proper solution for what you're trying to achieve. 7*635a8641SAndroid Build Coastguard Worker // Don't prematurely optimize, most likely you can just use a Lock. 8*635a8641SAndroid Build Coastguard Worker // 9*635a8641SAndroid Build Coastguard Worker // These classes implement a wrapper around ThreadLocalStorage::Slot. On 10*635a8641SAndroid Build Coastguard Worker // construction, they will allocate a TLS slot, and free the TLS slot on 11*635a8641SAndroid Build Coastguard Worker // destruction. No memory management (creation or destruction) is handled. This 12*635a8641SAndroid Build Coastguard Worker // means for uses of ThreadLocalPointer, you must correctly manage the memory 13*635a8641SAndroid Build Coastguard Worker // yourself, these classes will not destroy the pointer for you. There are no 14*635a8641SAndroid Build Coastguard Worker // at-thread-exit actions taken by these classes. 15*635a8641SAndroid Build Coastguard Worker // 16*635a8641SAndroid Build Coastguard Worker // ThreadLocalPointer<Type> wraps a Type*. It performs no creation or 17*635a8641SAndroid Build Coastguard Worker // destruction, so memory management must be handled elsewhere. The first call 18*635a8641SAndroid Build Coastguard Worker // to Get() on a thread will return NULL. You can update the pointer with a call 19*635a8641SAndroid Build Coastguard Worker // to Set(). 20*635a8641SAndroid Build Coastguard Worker // 21*635a8641SAndroid Build Coastguard Worker // ThreadLocalBoolean wraps a bool. It will default to false if it has never 22*635a8641SAndroid Build Coastguard Worker // been set otherwise with Set(). 23*635a8641SAndroid Build Coastguard Worker // 24*635a8641SAndroid Build Coastguard Worker // Thread Safety: An instance of ThreadLocalStorage is completely thread safe 25*635a8641SAndroid Build Coastguard Worker // once it has been created. If you want to dynamically create an instance, you 26*635a8641SAndroid Build Coastguard Worker // must of course properly deal with safety and race conditions. This means a 27*635a8641SAndroid Build Coastguard Worker // function-level static initializer is generally inappropiate. 28*635a8641SAndroid Build Coastguard Worker // 29*635a8641SAndroid Build Coastguard Worker // In Android, the system TLS is limited. 30*635a8641SAndroid Build Coastguard Worker // 31*635a8641SAndroid Build Coastguard Worker // Example usage: 32*635a8641SAndroid Build Coastguard Worker // // My class is logically attached to a single thread. We cache a pointer 33*635a8641SAndroid Build Coastguard Worker // // on the thread it was created on, so we can implement current(). 34*635a8641SAndroid Build Coastguard Worker // MyClass::MyClass() { 35*635a8641SAndroid Build Coastguard Worker // DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() == NULL); 36*635a8641SAndroid Build Coastguard Worker // Singleton<ThreadLocalPointer<MyClass> >::get()->Set(this); 37*635a8641SAndroid Build Coastguard Worker // } 38*635a8641SAndroid Build Coastguard Worker // 39*635a8641SAndroid Build Coastguard Worker // MyClass::~MyClass() { 40*635a8641SAndroid Build Coastguard Worker // DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() != NULL); 41*635a8641SAndroid Build Coastguard Worker // Singleton<ThreadLocalPointer<MyClass> >::get()->Set(NULL); 42*635a8641SAndroid Build Coastguard Worker // } 43*635a8641SAndroid Build Coastguard Worker // 44*635a8641SAndroid Build Coastguard Worker // // Return the current MyClass associated with the calling thread, can be 45*635a8641SAndroid Build Coastguard Worker // // NULL if there isn't a MyClass associated. 46*635a8641SAndroid Build Coastguard Worker // MyClass* MyClass::current() { 47*635a8641SAndroid Build Coastguard Worker // return Singleton<ThreadLocalPointer<MyClass> >::get()->Get(); 48*635a8641SAndroid Build Coastguard Worker // } 49*635a8641SAndroid Build Coastguard Worker 50*635a8641SAndroid Build Coastguard Worker #ifndef BASE_THREADING_THREAD_LOCAL_H_ 51*635a8641SAndroid Build Coastguard Worker #define BASE_THREADING_THREAD_LOCAL_H_ 52*635a8641SAndroid Build Coastguard Worker 53*635a8641SAndroid Build Coastguard Worker #include "base/macros.h" 54*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_local_storage.h" 55*635a8641SAndroid Build Coastguard Worker 56*635a8641SAndroid Build Coastguard Worker namespace base { 57*635a8641SAndroid Build Coastguard Worker 58*635a8641SAndroid Build Coastguard Worker template <typename Type> 59*635a8641SAndroid Build Coastguard Worker class ThreadLocalPointer { 60*635a8641SAndroid Build Coastguard Worker public: 61*635a8641SAndroid Build Coastguard Worker ThreadLocalPointer() = default; 62*635a8641SAndroid Build Coastguard Worker ~ThreadLocalPointer() = default; 63*635a8641SAndroid Build Coastguard Worker Get()64*635a8641SAndroid Build Coastguard Worker Type* Get() { 65*635a8641SAndroid Build Coastguard Worker return static_cast<Type*>(slot_.Get()); 66*635a8641SAndroid Build Coastguard Worker } 67*635a8641SAndroid Build Coastguard Worker Set(Type * ptr)68*635a8641SAndroid Build Coastguard Worker void Set(Type* ptr) { 69*635a8641SAndroid Build Coastguard Worker slot_.Set(const_cast<void*>(static_cast<const void*>(ptr))); 70*635a8641SAndroid Build Coastguard Worker } 71*635a8641SAndroid Build Coastguard Worker 72*635a8641SAndroid Build Coastguard Worker private: 73*635a8641SAndroid Build Coastguard Worker ThreadLocalStorage::Slot slot_; 74*635a8641SAndroid Build Coastguard Worker 75*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ThreadLocalPointer<Type>); 76*635a8641SAndroid Build Coastguard Worker }; 77*635a8641SAndroid Build Coastguard Worker 78*635a8641SAndroid Build Coastguard Worker class ThreadLocalBoolean { 79*635a8641SAndroid Build Coastguard Worker public: 80*635a8641SAndroid Build Coastguard Worker ThreadLocalBoolean() = default; 81*635a8641SAndroid Build Coastguard Worker ~ThreadLocalBoolean() = default; 82*635a8641SAndroid Build Coastguard Worker Get()83*635a8641SAndroid Build Coastguard Worker bool Get() { 84*635a8641SAndroid Build Coastguard Worker return tlp_.Get() != nullptr; 85*635a8641SAndroid Build Coastguard Worker } 86*635a8641SAndroid Build Coastguard Worker Set(bool val)87*635a8641SAndroid Build Coastguard Worker void Set(bool val) { 88*635a8641SAndroid Build Coastguard Worker tlp_.Set(val ? this : nullptr); 89*635a8641SAndroid Build Coastguard Worker } 90*635a8641SAndroid Build Coastguard Worker 91*635a8641SAndroid Build Coastguard Worker private: 92*635a8641SAndroid Build Coastguard Worker ThreadLocalPointer<void> tlp_; 93*635a8641SAndroid Build Coastguard Worker 94*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ThreadLocalBoolean); 95*635a8641SAndroid Build Coastguard Worker }; 96*635a8641SAndroid Build Coastguard Worker 97*635a8641SAndroid Build Coastguard Worker } // namespace base 98*635a8641SAndroid Build Coastguard Worker 99*635a8641SAndroid Build Coastguard Worker #endif // BASE_THREADING_THREAD_LOCAL_H_ 100