ThreadLocalStorage.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #pragma once
  2. #include "../C/Baselib_ThreadLocalStorage.h"
  3. namespace baselib
  4. {
  5. BASELIB_CPP_INTERFACE
  6. {
  7. // Thread Local Storage provides a variable that can be global but have different value in every thread.
  8. // For more details see Baselib_ThreadLocalStorage.
  9. // On some platforms this might be fiber local storage.
  10. //
  11. // Example of usage:
  12. // static ThreadLocalStorage<int32_t> threadErrorState;
  13. template<typename T>
  14. class ThreadLocalStorage
  15. {
  16. public:
  17. // by nature of TLS slots, they must be non-copyable, so
  18. ThreadLocalStorage(const ThreadLocalStorage & other) = delete;
  19. ThreadLocalStorage& operator=(const ThreadLocalStorage & other) = delete;
  20. ThreadLocalStorage()
  21. {
  22. static_assert(sizeof(T) <= sizeof(uintptr_t), "Provided type is too large to be stored in ThreadLocalStorage");
  23. handle = Baselib_TLS_Alloc();
  24. }
  25. ~ThreadLocalStorage()
  26. {
  27. if (IsValid())
  28. {
  29. Baselib_TLS_Free(handle);
  30. handle = InvalidTLSHandle;
  31. }
  32. }
  33. ThreadLocalStorage(ThreadLocalStorage && other)
  34. {
  35. // ensure that we don't leak local handle
  36. if (handle != InvalidTLSHandle)
  37. Baselib_TLS_Free(handle);
  38. handle = other.handle;
  39. other.handle = InvalidTLSHandle;
  40. }
  41. // Check if variable is valid.
  42. // The only case when variable might be invalid is if it was moved to some other instance.
  43. inline bool IsValid() const
  44. {
  45. return handle != InvalidTLSHandle;
  46. }
  47. // Resets value in all threads.
  48. void Reset()
  49. {
  50. Baselib_TLS_Free(handle);
  51. handle = Baselib_TLS_Alloc();
  52. }
  53. inline T operator=(T value)
  54. {
  55. Baselib_TLS_Set(handle, (uintptr_t)value);
  56. return value;
  57. }
  58. inline ThreadLocalStorage<T>& operator=(ThreadLocalStorage&& other)
  59. {
  60. // swap values
  61. Baselib_TLS_Handle t = handle;
  62. handle = other.handle;
  63. other.handle = t;
  64. return *this;
  65. }
  66. inline operator T() const
  67. {
  68. return (T)Baselib_TLS_Get(handle);
  69. }
  70. inline T operator->() const
  71. {
  72. return (T)Baselib_TLS_Get(handle);
  73. }
  74. inline T operator++()
  75. {
  76. *this = *this + 1;
  77. return *this;
  78. }
  79. inline T operator--()
  80. {
  81. *this = *this - 1;
  82. return *this;
  83. }
  84. private:
  85. Baselib_TLS_Handle handle = InvalidTLSHandle;
  86. static constexpr uintptr_t InvalidTLSHandle = UINTPTR_MAX;
  87. };
  88. }
  89. }