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