1// trdlocal.cpp - written and placed in the public domain by Wei Dai
2
3#include "pch.h"
4
5#ifndef CRYPTOPP_IMPORTS
6#ifdef THREADS_AVAILABLE
7
8#include "trdlocal.h"
9
10#ifdef HAS_WINTHREADS
11#include <windows.h>
12#endif
13
14NAMESPACE_BEGIN(CryptoPP)
15
16ThreadLocalStorage::Err::Err(const std::string& operation, int error)
17	: OS_Error(OTHER_ERROR, "ThreadLocalStorage: " + operation + " operation failed with error 0x" + IntToString(error, 16), operation, error)
18{
19}
20
21ThreadLocalStorage::ThreadLocalStorage()
22{
23#ifdef HAS_WINTHREADS
24	m_index = TlsAlloc();
25	if (m_index == TLS_OUT_OF_INDEXES)
26		throw Err("TlsAlloc", GetLastError());
27#else
28	int error = pthread_key_create(&m_index, NULL);
29	if (error)
30		throw Err("pthread_key_create", error);
31#endif
32}
33
34ThreadLocalStorage::~ThreadLocalStorage()
35{
36#ifdef HAS_WINTHREADS
37	if (!TlsFree(m_index))
38		throw Err("TlsFree", GetLastError());
39#else
40	int error = pthread_key_delete(m_index);
41	if (error)
42		throw Err("pthread_key_delete", error);
43#endif
44}
45
46void ThreadLocalStorage::SetValue(void *value)
47{
48#ifdef HAS_WINTHREADS
49	if (!TlsSetValue(m_index, value))
50		throw Err("TlsSetValue", GetLastError());
51#else
52	int error = pthread_setspecific(m_index, value);
53	if (error)
54		throw Err("pthread_key_getspecific", error);
55#endif
56}
57
58void *ThreadLocalStorage::GetValue() const
59{
60#ifdef HAS_WINTHREADS
61	void *result = TlsGetValue(m_index);
62	if (!result && GetLastError() != NO_ERROR)
63		throw Err("TlsGetValue", GetLastError());
64#else
65	void *result = pthread_getspecific(m_index);
66#endif
67	return result;
68}
69
70NAMESPACE_END
71
72#endif	// #ifdef THREADS_AVAILABLE
73#endif
74