Crypto++  5.6.5
Free C++ class library of cryptographic schemes
trdlocal.cpp
1 // trdlocal.cpp - originally written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 #include "config.h"
5 
6 #ifndef CRYPTOPP_IMPORTS
7 
8 #if !defined(NO_OS_DEPENDENCE) && defined(THREADS_AVAILABLE)
9 
10 #include "trdlocal.h"
11 
12 #ifdef HAS_WINTHREADS
13 #define WIN32_LEAN_AND_MEAN
14 #include <windows.h>
15 #endif
16 
17 NAMESPACE_BEGIN(CryptoPP)
18 
19 ThreadLocalStorage::Err::Err(const std::string& operation, int error)
20  : OS_Error(OTHER_ERROR, "ThreadLocalStorage: " + operation + " operation failed with error 0x" + IntToString(error, 16), operation, error)
21 {
22 }
23 
24 // Windows: "a process may have up to TLS_MINIMUM_AVAILABLE indexes (guaranteed to be greater than
25 // or equal to 64)", https://support.microsoft.com/en-us/help/94804/info-thread-local-storage-overview
26 ThreadLocalStorage::ThreadLocalStorage()
27 {
28 #ifdef HAS_WINTHREADS
29  m_index = TlsAlloc();
30  CRYPTOPP_ASSERT(m_index != TLS_OUT_OF_INDEXES);
31  if (m_index == TLS_OUT_OF_INDEXES)
32  throw Err("TlsAlloc", GetLastError());
33 #else
34  m_index = 0;
35  int error = pthread_key_create(&m_index, NULLPTR);
36  CRYPTOPP_ASSERT(!error);
37  if (error)
38  throw Err("pthread_key_create", error);
39 #endif
40 }
41 
42 ThreadLocalStorage::~ThreadLocalStorage() CRYPTOPP_THROW
43 {
44 #ifdef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
45  if (!std::uncaught_exception())
46 #else
47  try
48 #endif
49 #ifdef HAS_WINTHREADS
50  {
51  int rc = TlsFree(m_index);
52  CRYPTOPP_ASSERT(rc);
53  if (!rc)
54  throw Err("TlsFree", GetLastError());
55  }
56 #else
57  {
58  int error = pthread_key_delete(m_index);
59  CRYPTOPP_ASSERT(!error);
60  if (error)
61  throw Err("pthread_key_delete", error);
62  }
63 #endif
64 #ifndef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
65  catch(const Exception&)
66  {
67  }
68 #endif
69 }
70 
71 void ThreadLocalStorage::SetValue(void *value)
72 {
73 #ifdef HAS_WINTHREADS
74  if (!TlsSetValue(m_index, value))
75  throw Err("TlsSetValue", GetLastError());
76 #else
77  int error = pthread_setspecific(m_index, value);
78  if (error)
79  throw Err("pthread_key_getspecific", error);
80 #endif
81 }
82 
83 void *ThreadLocalStorage::GetValue() const
84 {
85 #ifdef HAS_WINTHREADS
86  void *result = TlsGetValue(m_index);
87  const DWORD dwRet = GetLastError();
88 
89  CRYPTOPP_ASSERT(result || (!result && (dwRet == NO_ERROR)));
90  if (!result && dwRet != NO_ERROR)
91  throw Err("TlsGetValue", dwRet);
92 #else
93  // Null is a valid return value. Posix does not provide a way to
94  // check for a "good" Null vs a "bad" Null (errno is not set).
95  void *result = pthread_getspecific(m_index);
96 #endif
97  return result;
98 }
99 
100 NAMESPACE_END
101 
102 #endif // THREADS_AVAILABLE
103 #endif // CRYPTOPP_IMPORTS
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:150
The operating system reported an error.
Definition: cryptlib.h:229
Library configuration file.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:60
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition: misc.h:582
Crypto++ library namespace.