PageRenderTime 123ms CodeModel.GetById 61ms app.highlight 7ms RepoModel.GetById 53ms app.codeStats 0ms

/mordor/thread_local_storage.h

http://github.com/mozy/mordor
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