mirror of
https://github.com/thunderbrewhq/common.git
synced 2025-12-12 03:02:29 +00:00
feat(thread): add OsTls functions
This commit is contained in:
parent
1eb1d281a9
commit
e1c516b188
5 changed files with 158 additions and 0 deletions
|
|
@ -3,6 +3,7 @@ file(GLOB COMMON_SOURCES
|
||||||
"objectalloc/*.cpp"
|
"objectalloc/*.cpp"
|
||||||
"ref/*.cpp"
|
"ref/*.cpp"
|
||||||
"string/*.cpp"
|
"string/*.cpp"
|
||||||
|
"thread/*.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(common STATIC
|
add_library(common STATIC
|
||||||
|
|
|
||||||
6
common/Thread.hpp
Normal file
6
common/Thread.hpp
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef COMMON_THREAD_HPP
|
||||||
|
#define COMMON_THREAD_HPP
|
||||||
|
|
||||||
|
#include "common/thread/Tls.hpp"
|
||||||
|
|
||||||
|
#endif
|
||||||
113
common/thread/Tls.cpp
Normal file
113
common/thread/Tls.cpp
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
#include "common/thread/Tls.hpp"
|
||||||
|
#include <storm/Thread.hpp>
|
||||||
|
|
||||||
|
#if defined(WHOA_SYSTEM_WIN)
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||||
|
#include <storm/Array.hpp>
|
||||||
|
#include <storm/List.hpp>
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||||
|
typedef void* TLSData;
|
||||||
|
|
||||||
|
struct TLSSlot : public TSLinkedNode<TLSSlot> {
|
||||||
|
TSGrowableArray<TLSData> storage;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace OsTls {
|
||||||
|
int8_t s_initialized;
|
||||||
|
int32_t s_nextIndex;
|
||||||
|
TSList<TLSSlot, TSGetLink<TLSSlot>> s_tlsCleanupList;
|
||||||
|
pthread_key_t s_tlsKey;
|
||||||
|
SCritSect s_tlsLock;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int32_t OsTlsAlloc() {
|
||||||
|
#if defined(WHOA_SYSTEM_WIN)
|
||||||
|
return TlsAlloc();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||||
|
OsTls::s_tlsLock.Enter();
|
||||||
|
|
||||||
|
if (!OsTls::s_initialized) {
|
||||||
|
OsTls::s_initialized = 1;
|
||||||
|
OsTls::s_nextIndex = 0;
|
||||||
|
pthread_key_create(&OsTls::s_tlsKey, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t index = OsTls::s_nextIndex++;
|
||||||
|
|
||||||
|
OsTls:: s_tlsLock.Leave();
|
||||||
|
|
||||||
|
return index;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void* OsTlsGetValue(uint32_t tlsIndex) {
|
||||||
|
#if defined(WHOA_SYSTEM_WIN)
|
||||||
|
return TlsGetValue(tlsIndex);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||||
|
if (!OsTls::s_initialized) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto slot = static_cast<TLSSlot*>(pthread_getspecific(OsTls::s_tlsKey));
|
||||||
|
|
||||||
|
if (!slot) {
|
||||||
|
OsTls::s_tlsLock.Enter();
|
||||||
|
|
||||||
|
slot = OsTls::s_tlsCleanupList.NewNode(1, 1, 0x8);
|
||||||
|
|
||||||
|
OsTls::s_tlsLock.Leave();
|
||||||
|
|
||||||
|
pthread_setspecific(OsTls::s_tlsKey, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot->storage.Count() > tlsIndex) {
|
||||||
|
return slot->storage[tlsIndex];
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t OsTlsSetValue(uint32_t tlsIndex, void* tlsValue) {
|
||||||
|
#if defined(WHOA_SYSTEM_WIN)
|
||||||
|
return TlsSetValue(tlsIndex, tlsValue);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||||
|
if (!OsTls::s_initialized) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto slot = static_cast<TLSSlot*>(pthread_getspecific(OsTls::s_tlsKey));
|
||||||
|
|
||||||
|
if (!slot) {
|
||||||
|
OsTls::s_tlsLock.Enter();
|
||||||
|
|
||||||
|
slot = OsTls::s_tlsCleanupList.NewNode(1, 1, 0x8);
|
||||||
|
|
||||||
|
OsTls::s_tlsLock.Leave();
|
||||||
|
|
||||||
|
pthread_setspecific(OsTls::s_tlsKey, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot->storage.Count() > tlsIndex) {
|
||||||
|
slot->storage[tlsIndex] = tlsValue;
|
||||||
|
} else {
|
||||||
|
slot->storage.GrowToFit(tlsIndex, 0);
|
||||||
|
slot->storage[tlsIndex] = tlsValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
12
common/thread/Tls.hpp
Normal file
12
common/thread/Tls.hpp
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef COMMON_THREAD_TLS_HPP
|
||||||
|
#define COMMON_THREAD_TLS_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
int32_t OsTlsAlloc();
|
||||||
|
|
||||||
|
void* OsTlsGetValue(uint32_t tlsIndex);
|
||||||
|
|
||||||
|
int32_t OsTlsSetValue(uint32_t tlsIndex, void* tlsValue);
|
||||||
|
|
||||||
|
#endif
|
||||||
26
test/Thread.cpp
Normal file
26
test/Thread.cpp
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#include "common/Thread.hpp"
|
||||||
|
#include "test/Test.hpp"
|
||||||
|
|
||||||
|
TEST_CASE("OsTlsAlloc", "[thread]") {
|
||||||
|
SECTION("allocates tls index") {
|
||||||
|
int32_t tlsIndex = OsTlsAlloc();
|
||||||
|
REQUIRE(tlsIndex >= 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("OsTlsSetValue", "[thread]") {
|
||||||
|
SECTION("sets value in tls index") {
|
||||||
|
int32_t tlsIndex = OsTlsAlloc();
|
||||||
|
uint32_t tlsValue = 123;
|
||||||
|
REQUIRE(OsTlsSetValue(tlsIndex, &tlsValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("OsTlsGetValue", "[thread]") {
|
||||||
|
SECTION("gets value in tls index") {
|
||||||
|
int32_t tlsIndex = OsTlsAlloc();
|
||||||
|
uint32_t tlsValue = 456;
|
||||||
|
OsTlsSetValue(tlsIndex, &tlsValue);
|
||||||
|
REQUIRE(OsTlsGetValue(tlsIndex) == &tlsValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue