Bug 756965 - Allow mozilla::ThreadLocal to store integer types smaller than, or as large as, a pointer. r=Waldo
authorMike Hommey <mh+mozilla@glandium.org>
Tue, 22 May 2012 08:43:55 +0200
changeset 98634 b3570567bd5d9a4616a6cf9358d3c8e57805beec
parent 98633 f60e0f7e3e6296bfe9f4573db10f1f4addec19ff
child 98635 7a1ae92b4b20230fea0bedf7c5db0664edad9c8a
push id1116
push userlsblakk@mozilla.com
push dateMon, 16 Jul 2012 19:38:18 +0000
treeherdermozilla-beta@95f959a8b4dc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs756965
milestone15.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 756965 - Allow mozilla::ThreadLocal to store integer types smaller than, or as large as, a pointer. r=Waldo
mfbt/ThreadLocal.h
tools/profiler/TableTicker.cpp
tools/profiler/sps_sampler.h
--- a/mfbt/ThreadLocal.h
+++ b/mfbt/ThreadLocal.h
@@ -67,62 +67,72 @@ template <typename T>
 class ThreadLocal
 {
 #if defined(XP_WIN)
     typedef unsigned long key_t;
 #else
     typedef pthread_key_t key_t;
 #endif
 
+    union Helper {
+      void *ptr;
+      T value;
+    };
+
   public:
     MOZ_WARN_UNUSED_RESULT inline bool init();
 
-    inline T* get() const;
+    inline T get() const;
 
-    inline bool set(const T* value);
+    inline bool set(const T value);
 
     bool initialized() const {
       return inited;
     }
 
   private:
     key_t key;
     bool inited;
 };
 
 template <typename T>
 inline bool
 ThreadLocal<T>::init() {
+  MOZ_STATIC_ASSERT(sizeof(T) <= sizeof(void *), "mozilla::ThreadLocal can't be used for types larger than a pointer");
   MOZ_ASSERT(!initialized());
 #ifdef XP_WIN
   key = TlsAlloc();
   inited = key != 0xFFFFFFFFUL; // TLS_OUT_OF_INDEXES
 #else
   inited = !pthread_key_create(&key, NULL);
 #endif
   return inited;
 }
 
 template <typename T>
-inline T*
+inline T
 ThreadLocal<T>::get() const {
   MOZ_ASSERT(initialized());
+  Helper h;
 #ifdef XP_WIN
-  return reinterpret_cast<T*>(TlsGetValue(key));
+  h.ptr = TlsGetValue(key);
 #else
-  return reinterpret_cast<T*>(pthread_getspecific(key));
+  h.ptr = pthread_getspecific(key);
 #endif
+  return h.value;
 }
 
 template <typename T>
 inline bool
-ThreadLocal<T>::set(const T* value) {
+ThreadLocal<T>::set(const T value) {
   MOZ_ASSERT(initialized());
+  Helper h;
+  h.value = value;
 #ifdef XP_WIN
-  return TlsSetValue(key, const_cast<T*>(value));
+  return TlsSetValue(key, h.ptr);
 #else
-  return !pthread_setspecific(key, value);
+  return !pthread_setspecific(key, h.ptr);
 #endif
 }
 
 } // namespace mozilla
 
 #endif // mozilla_TLS_h_
--- a/tools/profiler/TableTicker.cpp
+++ b/tools/profiler/TableTicker.cpp
@@ -64,18 +64,18 @@ using namespace mozilla;
  #endif
 #endif
 
 #if _MSC_VER
  #define snprintf _snprintf
 #endif
 
 
-mozilla::ThreadLocal<ProfileStack> tlsStack;
-mozilla::ThreadLocal<TableTicker> tlsTicker;
+mozilla::ThreadLocal<ProfileStack *> tlsStack;
+mozilla::ThreadLocal<TableTicker *> tlsTicker;
 // We need to track whether we've been initialized otherwise
 // we end up using tlsStack without initializing it.
 // Because tlsStack is totally opaque to us we can't reuse
 // it as the flag itself.
 bool stack_key_initialized;
 
 TimeStamp sLastTracerEvent;
 
--- a/tools/profiler/sps_sampler.h
+++ b/tools/profiler/sps_sampler.h
@@ -12,18 +12,18 @@
 #include "mozilla/Util.h"
 
 using mozilla::TimeStamp;
 using mozilla::TimeDuration;
 
 struct ProfileStack;
 class TableTicker;
 
-extern mozilla::ThreadLocal<ProfileStack> tlsStack;
-extern mozilla::ThreadLocal<TableTicker> tlsTicker;
+extern mozilla::ThreadLocal<ProfileStack *> tlsStack;
+extern mozilla::ThreadLocal<TableTicker *> tlsTicker;
 extern bool stack_key_initialized;
 
 #ifndef SAMPLE_FUNCTION_NAME
 # ifdef __GNUC__
 #  define SAMPLE_FUNCTION_NAME __FUNCTION__
 # elif defined(_MSC_VER)
 #  define SAMPLE_FUNCTION_NAME __FUNCTION__
 # else