/mordor/thread_local_storage.h
C Header | 100 lines | 84 code | 15 blank | 1 comment | 5 complexity | e7076c94e592704b86dff97408d93cfc MD5 | raw file
1#ifndef __MORDOR_THREAD_LOCAL_STORAGE_H__ 2#define __MORDOR_THREAD_LOCAL_STORAGE_H__ 3// Copyright (c) 2009 - Mozy, Inc. 4 5#include "predef.h" 6 7#include <boost/noncopyable.hpp> 8 9#ifdef WINDOWS 10#include <windows.h> 11#else 12#include <pthread.h> 13#endif 14 15#include "exception.h" 16 17namespace Mordor { 18 19template <class T> 20class ThreadLocalStorageBase : boost::noncopyable 21{ 22public: 23 ThreadLocalStorageBase() 24 { 25#ifdef WINDOWS 26 m_key = TlsAlloc(); 27 if (m_key == TLS_OUT_OF_INDEXES) 28 MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("TlsAlloc"); 29#else 30 int rc = pthread_key_create(&m_key, NULL); 31 if (rc) 32 MORDOR_THROW_EXCEPTION_FROM_ERROR_API(rc, "pthread_create_specific"); 33#endif 34 } 35 36 ~ThreadLocalStorageBase() 37 { 38#ifdef WINDOWS 39 TlsFree(m_key); 40#else 41 pthread_key_delete(m_key); 42#endif 43 } 44 45 typename boost::enable_if_c<sizeof(T) <= sizeof(void *)>::type set(const T &t) 46 { 47#ifdef WINDOWS 48 if (!TlsSetValue(m_key, (LPVOID)t)) 49 MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("TlsSetValue"); 50#else 51 int rc = pthread_setspecific(m_key, (const void *)t); 52 if (rc) 53 MORDOR_THROW_EXCEPTION_FROM_ERROR_API(rc, "pthread_setspecific"); 54#endif 55 } 56 57 T get() const 58 { 59#ifdef WINDOWS 60#pragma warning(push) 61#pragma warning(disable: 4800) 62 DWORD lastError = GetLastError(); 63 LPVOID result = TlsGetValue(m_key); 64 SetLastError(lastError); 65 return (T)result; 66#pragma warning(pop) 67#else 68 return (T)pthread_getspecific(m_key); 69#endif 70 } 71 72 operator T() const { return get(); } 73 74private: 75#ifdef WINDOWS 76 DWORD m_key; 77#else 78 pthread_key_t m_key; 79#endif 80}; 81 82template <class T> 83class ThreadLocalStorage : public ThreadLocalStorageBase<T> 84{ 85public: 86 T operator =(T t) { ThreadLocalStorageBase<T>::set(t); return t; } 87}; 88 89template <class T> 90class ThreadLocalStorage<T *> : public ThreadLocalStorageBase<T *> 91{ 92public: 93 T * operator =(T *const t) { ThreadLocalStorageBase<T *>::set(t); return t; } 94 T & operator*() { return *ThreadLocalStorageBase<T *>::get(); } 95 T * operator->() { return ThreadLocalStorageBase<T *>::get(); } 96}; 97 98}; 99 100#endif