Bug 1093823 - Avoid valgrind report from ThreadLocal<bool>. r=froydnj
authorTom Tromey <tom@tromey.com>
Fri, 07 Nov 2014 08:41:00 -0500
changeset 241747 e6e89ea52d0903586648fc30e314f742e53255f9
parent 241746 b7379df4f3e7f9a9eb3876016c57c2e54d573832
child 241748 92827522deee8bc3971acdb61477667887e696b2
push id660
push userraliiev@mozilla.com
push dateWed, 18 Feb 2015 20:30:48 +0000
treeherdermozilla-release@49e493494178 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1093823
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1093823 - Avoid valgrind report from ThreadLocal<bool>. r=froydnj
mfbt/ThreadLocal.h
--- a/mfbt/ThreadLocal.h
+++ b/mfbt/ThreadLocal.h
@@ -25,16 +25,17 @@ extern "C" {
 #else
 #  include <pthread.h>
 #  include <signal.h>
 #endif
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/NullPtr.h"
+#include "mozilla/TypeTraits.h"
 
 namespace mozilla {
 
 // sig_safe_t denotes an atomic type which can be read or stored in a single
 // instruction.  This means that data of this type is safe to be manipulated
 // from a signal handler, or other similar asynchronous execution contexts.
 #if defined(XP_WIN)
 typedef unsigned long sig_safe_t;
@@ -73,20 +74,30 @@ template<typename T>
 class ThreadLocal
 {
 #if defined(XP_WIN)
   typedef unsigned long key_t;
 #else
   typedef pthread_key_t key_t;
 #endif
 
-  union Helper
+  // 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
   {
-    void* mPtr;
-    T mValue;
+    typedef uintptr_t Type;
+  };
+
+  template<typename S>
+  struct Helper<S *>
+  {
+    typedef S *Type;
   };
 
 public:
   MOZ_WARN_UNUSED_RESULT inline bool init();
 
   inline T get() const;
 
   inline void set(const T aValue);
@@ -97,16 +108,19 @@ private:
   key_t mKey;
   bool mInited;
 };
 
 template<typename T>
 inline bool
 ThreadLocal<T>::init()
 {
+  static_assert(mozilla::IsPointer<T>::value || mozilla::IsIntegral<T>::value,
+                "mozilla::ThreadLocal must be used with a pointer or "
+                "integral type");
   static_assert(sizeof(T) <= sizeof(void*),
                 "mozilla::ThreadLocal can't be used for types larger than "
                 "a pointer");
   MOZ_ASSERT(!initialized());
 #ifdef XP_WIN
   mKey = TlsAlloc();
   mInited = mKey != 0xFFFFFFFFUL; // TLS_OUT_OF_INDEXES
 #else
@@ -115,36 +129,35 @@ ThreadLocal<T>::init()
   return mInited;
 }
 
 template<typename T>
 inline T
 ThreadLocal<T>::get() const
 {
   MOZ_ASSERT(initialized());
-  Helper h;
+  void* h;
 #ifdef XP_WIN
-  h.mPtr = TlsGetValue(mKey);
+  h = TlsGetValue(mKey);
 #else
-  h.mPtr = pthread_getspecific(mKey);
+  h = pthread_getspecific(mKey);
 #endif
-  return h.mValue;
+  return static_cast<T>(reinterpret_cast<typename Helper<T>::Type>(h));
 }
 
 template<typename T>
 inline void
 ThreadLocal<T>::set(const T aValue)
 {
   MOZ_ASSERT(initialized());
-  Helper h;
-  h.mValue = aValue;
+  void* h = reinterpret_cast<void*>(static_cast<typename Helper<T>::Type>(aValue));
 #ifdef XP_WIN
-  bool succeeded = TlsSetValue(mKey, h.mPtr);
+  bool succeeded = TlsSetValue(mKey, h);
 #else
-  bool succeeded = !pthread_setspecific(mKey, h.mPtr);
+  bool succeeded = !pthread_setspecific(mKey, h);
 #endif
   if (!succeeded) {
     MOZ_CRASH();
   }
 }
 
 } // namespace mozilla