Crypto++  6.1
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 #include "stdcpp.h"
12 
13 #ifdef HAS_WINTHREADS
14 #define WIN32_LEAN_AND_MEAN
15 #include <windows.h>
16 #endif
17 
18 #if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
19 # pragma GCC diagnostic ignored "-Wc++11-compat"
20 #endif
21 
22 NAMESPACE_BEGIN(CryptoPP)
23 
24 ThreadLocalStorage::Err::Err(const std::string& operation, int error)
25  : OS_Error(OTHER_ERROR, "ThreadLocalStorage: " + operation + " operation failed with error 0x" + IntToString(error, 16), operation, error)
26 {
27 }
28 
29 // Windows: "a process may have up to TLS_MINIMUM_AVAILABLE indexes (guaranteed to be greater than
30 // or equal to 64)", https://support.microsoft.com/en-us/help/94804/info-thread-local-storage-overview
31 ThreadLocalStorage::ThreadLocalStorage()
32 {
33 #ifdef HAS_WINTHREADS
34  m_index = TlsAlloc();
35  CRYPTOPP_ASSERT(m_index != TLS_OUT_OF_INDEXES);
36  if (m_index == TLS_OUT_OF_INDEXES)
37  throw Err("TlsAlloc", GetLastError());
38 #else
39  m_index = 0;
40  int error = pthread_key_create(&m_index, NULLPTR);
41  CRYPTOPP_ASSERT(!error);
42  if (error)
43  throw Err("pthread_key_create", error);
44 #endif
45 }
46 
47 ThreadLocalStorage::~ThreadLocalStorage() CRYPTOPP_THROW
48 {
49 #if defined(CRYPTOPP_CXX17_EXCEPTIONS)
50  if (std::uncaught_exceptions() == 0)
51 #elif defined(CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE)
52  if (std::uncaught_exception() == false)
53 #else
54  try
55 #endif
56 #ifdef HAS_WINTHREADS
57  {
58  int rc = TlsFree(m_index);
59  CRYPTOPP_ASSERT(rc);
60  if (!rc)
61  throw Err("TlsFree", GetLastError());
62  }
63 #else
64  {
65  int error = pthread_key_delete(m_index);
66  CRYPTOPP_ASSERT(!error);
67  if (error)
68  throw Err("pthread_key_delete", error);
69  }
70 #endif
71 #if !defined(CRYPTOPP_CXX17_EXCEPTIONS) && !defined(CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE)
72  catch(const Exception&)
73  {
74  }
75 #endif
76 }
77 
78 void ThreadLocalStorage::SetValue(void *value)
79 {
80 #ifdef HAS_WINTHREADS
81  if (!TlsSetValue(m_index, value))
82  throw Err("TlsSetValue", GetLastError());
83 #else
84  int error = pthread_setspecific(m_index, value);
85  if (error)
86  throw Err("pthread_key_getspecific", error);
87 #endif
88 }
89 
90 void *ThreadLocalStorage::GetValue() const
91 {
92 #ifdef HAS_WINTHREADS
93  void *result = TlsGetValue(m_index);
94  const DWORD dwRet = GetLastError();
95 
96  CRYPTOPP_ASSERT(result || (!result && (dwRet == NO_ERROR)));
97  if (!result && dwRet != NO_ERROR)
98  throw Err("TlsGetValue", dwRet);
99 #else
100  // Null is a valid return value. Posix does not provide a way to
101  // check for a "good" Null vs a "bad" Null (errno is not set).
102  void *result = pthread_getspecific(m_index);
103 #endif
104  return result;
105 }
106 
107 NAMESPACE_END
108 
109 #endif // THREADS_AVAILABLE
110 #endif // CRYPTOPP_IMPORTS
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:155
The operating system reported an error.
Definition: cryptlib.h:234
Library configuration file.
Common C++ header files.
Precompiled header 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:576
Crypto++ library namespace.