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