thread_local.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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. // WARNING: Thread local storage is a bit tricky to get right. Please make sure
  5. // that this is really the proper solution for what you're trying to achieve.
  6. // Don't prematurely optimize, most likely you can just use a Lock.
  7. //
  8. // These classes implement a wrapper around ThreadLocalStorage::Slot. On
  9. // construction, they will allocate a TLS slot, and free the TLS slot on
  10. // destruction. No memory management (creation or destruction) is handled. This
  11. // means for uses of ThreadLocalPointer, you must correctly manage the memory
  12. // yourself, these classes will not destroy the pointer for you. There are no
  13. // at-thread-exit actions taken by these classes.
  14. //
  15. // ThreadLocalPointer<Type> wraps a Type*. It performs no creation or
  16. // destruction, so memory management must be handled elsewhere. The first call
  17. // to Get() on a thread will return NULL. You can update the pointer with a call
  18. // to Set().
  19. //
  20. // ThreadLocalBoolean wraps a bool. It will default to false if it has never
  21. // been set otherwise with Set().
  22. //
  23. // Thread Safety: An instance of ThreadLocalStorage is completely thread safe
  24. // once it has been created. If you want to dynamically create an instance, you
  25. // must of course properly deal with safety and race conditions.
  26. //
  27. // In Android, the system TLS is limited.
  28. //
  29. // Example usage:
  30. // // My class is logically attached to a single thread. We cache a pointer
  31. // // on the thread it was created on, so we can implement current().
  32. // MyClass::MyClass() {
  33. // DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() == NULL);
  34. // Singleton<ThreadLocalPointer<MyClass> >::get()->Set(this);
  35. // }
  36. //
  37. // MyClass::~MyClass() {
  38. // DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() != NULL);
  39. // Singleton<ThreadLocalPointer<MyClass> >::get()->Set(NULL);
  40. // }
  41. //
  42. // // Return the current MyClass associated with the calling thread, can be
  43. // // NULL if there isn't a MyClass associated.
  44. // MyClass* MyClass::current() {
  45. // return Singleton<ThreadLocalPointer<MyClass> >::get()->Get();
  46. // }
  47. #ifndef BASE_THREADING_THREAD_LOCAL_H_
  48. #define BASE_THREADING_THREAD_LOCAL_H_
  49. #include <memory>
  50. #include "base/dcheck_is_on.h"
  51. #include "base/memory/ptr_util.h"
  52. #include "base/threading/thread_local_internal.h"
  53. #include "base/threading/thread_local_storage.h"
  54. namespace base {
  55. template <typename T>
  56. class ThreadLocalPointer {
  57. public:
  58. ThreadLocalPointer() = default;
  59. ThreadLocalPointer(const ThreadLocalPointer&) = delete;
  60. ThreadLocalPointer& operator=(const ThreadLocalPointer&) = delete;
  61. ~ThreadLocalPointer() = default;
  62. T* Get() const { return static_cast<T*>(slot_.Get()); }
  63. void Set(T* ptr) {
  64. slot_.Set(const_cast<void*>(static_cast<const void*>(ptr)));
  65. }
  66. private:
  67. ThreadLocalStorage::Slot slot_;
  68. };
  69. // A ThreadLocalOwnedPointer<T> is like a ThreadLocalPointer<T> except that
  70. // pointers handed to it are owned and automatically deleted during their
  71. // associated thread's exit phase (or when replaced if Set() is invoked multiple
  72. // times on the same thread).
  73. // The ThreadLocalOwnedPointer instance itself can only be destroyed when no
  74. // threads, other than the one it is destroyed on, have remaining state set in
  75. // it. Typically this means that ThreadLocalOwnedPointer instances are held in
  76. // static storage or at the very least only recycled in the single-threaded
  77. // phase between tests in the same process.
  78. #if DCHECK_IS_ON()
  79. template <typename T>
  80. using ThreadLocalOwnedPointer = internal::CheckedThreadLocalOwnedPointer<T>;
  81. #else // DCHECK_IS_ON()
  82. template <typename T>
  83. class ThreadLocalOwnedPointer {
  84. public:
  85. ThreadLocalOwnedPointer() = default;
  86. ThreadLocalOwnedPointer(const ThreadLocalOwnedPointer&) = delete;
  87. ThreadLocalOwnedPointer& operator=(const ThreadLocalOwnedPointer&) = delete;
  88. ~ThreadLocalOwnedPointer() {
  89. // Assume that this thread is the only one with potential state left. This
  90. // is verified in ~CheckedThreadLocalOwnedPointer().
  91. Set(nullptr);
  92. }
  93. T* Get() const { return static_cast<T*>(slot_.Get()); }
  94. // Sets a new value, returns the old.
  95. std::unique_ptr<T> Set(std::unique_ptr<T> ptr) {
  96. auto existing = WrapUnique(Get());
  97. slot_.Set(const_cast<void*>(static_cast<const void*>(ptr.release())));
  98. return existing;
  99. }
  100. T& operator*() { return *Get(); }
  101. private:
  102. static void DeleteTlsPtr(void* ptr) { delete static_cast<T*>(ptr); }
  103. ThreadLocalStorage::Slot slot_{&DeleteTlsPtr};
  104. };
  105. #endif // DCHECK_IS_ON()
  106. class ThreadLocalBoolean {
  107. public:
  108. ThreadLocalBoolean() = default;
  109. ThreadLocalBoolean(const ThreadLocalBoolean&) = delete;
  110. ThreadLocalBoolean& operator=(const ThreadLocalBoolean&) = delete;
  111. ~ThreadLocalBoolean() = default;
  112. bool Get() const { return tlp_.Get() != nullptr; }
  113. void Set(bool val) { tlp_.Set(val ? this : nullptr); }
  114. private:
  115. ThreadLocalPointer<void> tlp_;
  116. };
  117. } // namespace base
  118. #endif // BASE_THREADING_THREAD_LOCAL_H_