thread_local.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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/check_op.h"
  51. #include "base/macros.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() = default;
  60. T* Get() const { return static_cast<T*>(slot_.Get()); }
  61. void Set(T* ptr) {
  62. slot_.Set(const_cast<void*>(static_cast<const void*>(ptr)));
  63. }
  64. private:
  65. ThreadLocalStorage::Slot slot_;
  66. DISALLOW_COPY_AND_ASSIGN(ThreadLocalPointer<T>);
  67. };
  68. // A ThreadLocalOwnedPointer<T> is like a ThreadLocalPointer<T> except that
  69. // pointers handed to it are owned and automatically deleted during their
  70. // associated thread's exit phase (or when replaced if Set() is invoked multiple
  71. // times on the same thread).
  72. // The ThreadLocalOwnedPointer instance itself can only be destroyed when no
  73. // threads, other than the one it is destroyed on, have remaining state set in
  74. // it. Typically this means that ThreadLocalOwnedPointer instances are held in
  75. // static storage or at the very least only recycled in the single-threaded
  76. // phase between tests in the same process.
  77. #if DCHECK_IS_ON()
  78. template <typename T>
  79. using ThreadLocalOwnedPointer = internal::CheckedThreadLocalOwnedPointer<T>;
  80. #else // DCHECK_IS_ON()
  81. template <typename T>
  82. class ThreadLocalOwnedPointer {
  83. public:
  84. ThreadLocalOwnedPointer() = default;
  85. ~ThreadLocalOwnedPointer() {
  86. // Assume that this thread is the only one with potential state left. This
  87. // is verified in ~CheckedThreadLocalOwnedPointer().
  88. Set(nullptr);
  89. }
  90. T* Get() const { return static_cast<T*>(slot_.Get()); }
  91. void Set(std::unique_ptr<T> ptr) {
  92. delete Get();
  93. slot_.Set(const_cast<void*>(static_cast<const void*>(ptr.release())));
  94. }
  95. private:
  96. static void DeleteTlsPtr(void* ptr) { delete static_cast<T*>(ptr); }
  97. ThreadLocalStorage::Slot slot_{&DeleteTlsPtr};
  98. DISALLOW_COPY_AND_ASSIGN(ThreadLocalOwnedPointer<T>);
  99. };
  100. #endif // DCHECK_IS_ON()
  101. class ThreadLocalBoolean {
  102. public:
  103. ThreadLocalBoolean() = default;
  104. ~ThreadLocalBoolean() = default;
  105. bool Get() const { return tlp_.Get() != nullptr; }
  106. void Set(bool val) { tlp_.Set(val ? this : nullptr); }
  107. private:
  108. ThreadLocalPointer<void> tlp_;
  109. DISALLOW_COPY_AND_ASSIGN(ThreadLocalBoolean);
  110. };
  111. } // namespace base
  112. #endif // BASE_THREADING_THREAD_LOCAL_H_