Bug 1399031 - Add a Tls{Get,Set}Value-based ThreadLocal implementation for Windows. r?froydnj draft
authorMike Hommey <mh+mozilla@glandium.org>
Tue, 12 Sep 2017 16:04:17 +0900
changeset 662960 03bf602b1e1c23a7f5e674ce020010d779d6dac4
parent 662959 d789cd7fbc6e60dc6610302d475b720322f3b5b8
child 662961 de372b1f8dfa582057376a56938d8254031ea60d
push id79254
push userbmo:mh+mozilla@glandium.org
push dateTue, 12 Sep 2017 09:42:10 +0000
reviewersfroydnj
bugs1399031
milestone57.0a1
Bug 1399031 - Add a Tls{Get,Set}Value-based ThreadLocal implementation for Windows. r?froydnj
mfbt/ThreadLocal.h
--- a/mfbt/ThreadLocal.h
+++ b/mfbt/ThreadLocal.h
@@ -67,36 +67,67 @@ namespace detail {
  * }
  *
  * // Set the TLS value
  * tlsKey.set(123);
  *
  * // Get the TLS value
  * int value = tlsKey.get();
  */
-#ifndef XP_WIN
+
+// Integral types narrower than void* must be extended to avoid
+// warnings from valgrind on some platforms.  This helper type
+// achieves that without penalizing the common case of ThreadLocals
+// instantiated using a pointer type.
+template<typename S>
+struct Helper
+{
+  typedef uintptr_t Type;
+};
+
+template<typename S>
+struct Helper<S *>
+{
+  typedef S *Type;
+};
+
+#ifdef XP_WIN
 template<typename T>
 class ThreadLocalKeyTrait
 {
-  // Integral types narrower than void* must be extended to avoid
-  // warnings from valgrind on some platforms.  This helper type
-  // achieves that without penalizing the common case of ThreadLocals
-  // instantiated using a pointer type.
-  template<typename S>
-  struct Helper
-  {
-    typedef uintptr_t Type;
-  };
+public:
+  ThreadLocalKeyTrait()
+    : mKey(TLS_OUT_OF_INDEXES)
+  {}
+
+  inline bool initialized() const {
+    return mKey != TLS_OUT_OF_INDEXES;
+  }
+
+  inline void init() {
+    mKey = TlsAlloc();
+  }
 
-  template<typename S>
-  struct Helper<S *>
-  {
-    typedef S *Type;
-  };
+  inline T get() const {
+    void* h = TlsGetValue(mKey);
+    return static_cast<T>(reinterpret_cast<typename Helper<T>::Type>(h));
+  }
 
+  inline bool set(const T aValue) {
+    void* h = reinterpret_cast<void*>(static_cast<typename Helper<T>::Type>(aValue));
+    return TlsSetValue(mKey, h);
+  }
+
+private:
+  unsigned long mKey;
+};
+#else
+template<typename T>
+class ThreadLocalKeyTrait
+{
 public:
   ThreadLocalKeyTrait()
     : mKey(0), mInited(false)
   {}
 
   inline bool initialized() const {
     return mInited;
   }
@@ -142,17 +173,17 @@ public:
     mValue = aValue;
     return true;
   }
 
 private:
   T mValue;
 };
 
-template<typename T, typename Trait>
+template<typename T, typename Trait = ThreadLocalKeyTrait<T>>
 class ThreadLocal: public Trait
 {
 public:
   MOZ_MUST_USE inline bool init();
 
   void infallibleInit() {
     MOZ_RELEASE_ASSERT(init(), "Infallible TLS initialization failed");
   }
@@ -200,15 +231,15 @@ ThreadLocal<T, Trait>::set(const T aValu
 
 #ifdef MOZ_HAS_THREAD_LOCAL
 #if defined(XP_WIN) || defined(MACOSX_HAS_THREAD_LOCAL)
 #define MOZ_THREAD_LOCAL(TYPE) thread_local mozilla::detail::ThreadLocal<TYPE, mozilla::detail::ThreadLocalNativeTrait<TYPE>>
 #else
 #define MOZ_THREAD_LOCAL(TYPE) __thread mozilla::detail::ThreadLocal<TYPE, mozilla::detail::ThreadLocalNativeTrait<TYPE>>
 #endif
 #else
-#define MOZ_THREAD_LOCAL(TYPE) mozilla::detail::ThreadLocal<TYPE, mozilla::detail::ThreadLocalKeyTrait<TYPE>>
+#define MOZ_THREAD_LOCAL(TYPE) mozilla::detail::ThreadLocal<TYPE>
 #endif
 
 } // namespace detail
 } // namespace mozilla
 
 #endif /* mozilla_ThreadLocal_h */