feat(thread): add OsTls functions

This commit is contained in:
fallenoak 2022-12-29 22:18:14 -06:00 committed by GitHub
parent 1eb1d281a9
commit e1c516b188
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 158 additions and 0 deletions

View file

@ -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
View 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
View 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
View 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
View 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);
}
}