Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
2.2 KiB

  1. // trdlocal.cpp - written and placed in the public domain by Wei Dai
  2. #include "pch.h"
  3. #include "config.h"
  4. // TODO: fix this when more complete C++11 support is cut-in
  5. #if CRYPTOPP_MSC_VERSION
  6. # pragma warning(disable: 4297)
  7. #endif
  8. #ifndef CRYPTOPP_IMPORTS
  9. #ifdef THREADS_AVAILABLE
  10. #include "trdlocal.h"
  11. #ifdef HAS_WINTHREADS
  12. #include <windows.h>
  13. #endif
  14. NAMESPACE_BEGIN(CryptoPP)
  15. ThreadLocalStorage::Err::Err(const std::string& operation, int error)
  16. : OS_Error(OTHER_ERROR, "ThreadLocalStorage: " + operation + " operation failed with error 0x" + IntToString(error, 16), operation, error)
  17. {
  18. }
  19. ThreadLocalStorage::ThreadLocalStorage()
  20. {
  21. #ifdef HAS_WINTHREADS
  22. m_index = TlsAlloc();
  23. assert(m_index != TLS_OUT_OF_INDEXES);
  24. if (m_index == TLS_OUT_OF_INDEXES)
  25. throw Err("TlsAlloc", GetLastError());
  26. #else
  27. m_index = 0;
  28. int error = pthread_key_create(&m_index, NULL);
  29. assert(!error);
  30. if (error)
  31. throw Err("pthread_key_create", error);
  32. #endif
  33. }
  34. ThreadLocalStorage::~ThreadLocalStorage() CRYPTOPP_THROW
  35. {
  36. #ifdef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
  37. if (!std::uncaught_exception())
  38. #else
  39. try
  40. #endif
  41. #ifdef HAS_WINTHREADS
  42. {
  43. int rc = TlsFree(m_index);
  44. assert(rc);
  45. if (!rc)
  46. throw Err("TlsFree", GetLastError());
  47. }
  48. #else
  49. {
  50. int error = pthread_key_delete(m_index);
  51. assert(!error);
  52. if (error)
  53. throw Err("pthread_key_delete", error);
  54. }
  55. #endif
  56. #ifndef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
  57. catch(const Exception&)
  58. {
  59. }
  60. #endif
  61. }
  62. void ThreadLocalStorage::SetValue(void *value)
  63. {
  64. #ifdef HAS_WINTHREADS
  65. if (!TlsSetValue(m_index, value))
  66. throw Err("TlsSetValue", GetLastError());
  67. #else
  68. int error = pthread_setspecific(m_index, value);
  69. if (error)
  70. throw Err("pthread_key_getspecific", error);
  71. #endif
  72. }
  73. void *ThreadLocalStorage::GetValue() const
  74. {
  75. #ifdef HAS_WINTHREADS
  76. void *result = TlsGetValue(m_index);
  77. const DWORD dwRet = GetLastError();
  78. assert(result || (!result && (dwRet == NO_ERROR)));
  79. if (!result && dwRet != NO_ERROR)
  80. throw Err("TlsGetValue", dwRet);
  81. #else
  82. // Null is a valid return value. Posix does not provide a way to
  83. // check for a "good" Null vs a "bad" Null (errno is not set).
  84. void *result = pthread_getspecific(m_index);
  85. #endif
  86. return result;
  87. }
  88. NAMESPACE_END
  89. #endif // #ifdef THREADS_AVAILABLE
  90. #endif