#include "tpt-thread-local.h" #ifdef __MINGW32__ # include # include # include void *ThreadLocalCommon::Get() const { // https://stackoverflow.com/questions/16552710/how-do-you-get-the-start-and-end-addresses-of-a-custom-elf-section extern ThreadLocalCommon __start_tpt_tls; extern ThreadLocalCommon __stop_tpt_tls; static pthread_once_t once = PTHREAD_ONCE_INIT; static pthread_key_t key; struct ThreadLocalEntry { void *ptr; }; auto *staticsBegin = &__start_tpt_tls; auto *staticsEnd = &__stop_tpt_tls; pthread_once(&once, []() -> void { assert(!pthread_key_create(&key, [](void *opaque) -> void { auto *staticsBegin = &__start_tpt_tls; auto *staticsEnd = &__stop_tpt_tls; auto staticsCount = staticsEnd - staticsBegin; auto *liveObjects = reinterpret_cast(opaque); if (liveObjects) { for (auto i = 0; i < staticsCount; ++i) { if (liveObjects[i].ptr) { staticsBegin[i].dtor(liveObjects[i].ptr); free(liveObjects[i].ptr); } } free(liveObjects); } })); }); auto *liveObjects = reinterpret_cast(pthread_getspecific(key)); if (!liveObjects) { auto staticsCount = staticsEnd - staticsBegin; liveObjects = reinterpret_cast(calloc(staticsCount, sizeof(ThreadLocalEntry))); assert(liveObjects); assert(!pthread_setspecific(key, reinterpret_cast(liveObjects))); } auto idx = this - staticsBegin; auto &entry = liveObjects[idx]; if (!entry.ptr) { entry.ptr = malloc(staticsBegin[idx].size); assert(entry.ptr); staticsBegin[idx].ctor(entry.ptr); } return entry.ptr; } #endif