AuroraRuntime/Source/Threading/Threads/TLSView.cpp

165 lines
3.8 KiB
C++
Raw Normal View History

2021-06-27 21:25:29 +00:00
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: TLSView.cpp
Date: 2021-6-12
Author: Reece
***/
2021-09-30 14:57:41 +00:00
#include <Source/RuntimeInternal.hpp>
2021-06-27 21:25:29 +00:00
#include "TLSView.hpp"
#include "../Primitives/ThreadCookie.hpp"
2021-06-27 21:25:29 +00:00
namespace Aurora::Threading::Threads
{
static AuUInt32 uAtomicCounter {};
static thread_local AuUInt32 tlsThreadIndex { };
2023-04-30 13:46:36 +00:00
static const auto kMaxMaxLinearThreads = AuNumericLimits<AuUInt16>::max() / 10;
AuUInt32 GetThreadKey()
2021-06-27 21:25:29 +00:00
{
auto &uKey = tlsThreadIndex;
2021-06-27 21:25:29 +00:00
if (!uKey)
2021-06-27 21:25:29 +00:00
{
uKey = AuAtomicAdd(&uAtomicCounter, 1u);
2021-06-27 21:25:29 +00:00
if (uKey > kMaxMaxLinearThreads) [[unlikely]]
{
uKey = uAtomicCounter = kMaxMaxLinearThreads + 1;
}
2021-06-27 21:25:29 +00:00
}
return uKey;
}
void SetThreadKey(AuUInt32 uThreadKey)
{
tlsThreadIndex = uThreadKey;
2021-06-27 21:25:29 +00:00
}
struct ViewEntry
2021-06-27 21:25:29 +00:00
{
~ViewEntry();
2021-06-27 21:25:29 +00:00
void *pVoid {};
TLSView::TlsCb deinit;
};
2021-06-27 21:25:29 +00:00
struct ViewContext
2021-06-27 21:25:29 +00:00
{
// 256 bytes, less than some of microsofts stupid stl thread primitives
// so, ill take this as acceptable
2023-04-30 13:46:36 +00:00
/*void **/ ViewEntry table[64];
AuThreadPrimitives::Mutex mutex;
AuList<AuSPtr<ViewEntry>> ptrs;
AuHashMap<AuUInt, AuSPtr<ViewEntry>> hashMap;
2021-06-27 21:25:29 +00:00
ViewEntry &GetHandleReference();
};
ViewEntry::~ViewEntry()
{
if (this->pVoid && this->deinit)
2021-06-27 21:25:29 +00:00
{
this->deinit(this->pVoid);
2021-06-27 21:25:29 +00:00
}
2023-04-30 08:02:13 +00:00
if (this->pVoid)
{
AuMemory::_Free(this->pVoid);
this->pVoid = nullptr;
}
}
2021-06-27 21:25:29 +00:00
ViewEntry &ViewContext::GetHandleReference()
{
auto uKey = GetThreadKey();
if (uKey >= AuArraySize(this->table))
2021-06-27 21:25:29 +00:00
{
AU_LOCK_GUARD(this->mutex);
if (uKey > kMaxMaxLinearThreads) [[unlikely]]
2021-06-27 21:25:29 +00:00
{
auto &sharedRef = this->hashMap[Primitives::GetThreadCookie()];
if (!sharedRef)
{
sharedRef = AuMakeSharedPanic<ViewEntry>();
}
return *sharedRef.get();
2021-06-27 21:25:29 +00:00
}
uKey -= AuArraySize(this->table);
2023-04-30 13:46:36 +00:00
if (uKey >= this->ptrs.size())
2021-06-27 21:25:29 +00:00
{
2023-04-30 13:46:36 +00:00
this->ptrs.reserve(uKey * 2);
this->ptrs.resize(uKey + 1);
2021-06-27 21:25:29 +00:00
}
2023-04-30 13:46:36 +00:00
auto &sharedRef = this->ptrs[uKey];
if (!sharedRef)
2021-06-27 21:25:29 +00:00
{
sharedRef = AuMakeSharedPanic<ViewEntry>();
2021-06-27 21:25:29 +00:00
}
return *sharedRef.get();
}
else
{
return this->table[uKey];
2021-06-27 21:25:29 +00:00
}
}
void *TLSView::InitTLS(TLSKey &key, AuMach length, const TlsCb &init, const TlsCb &deinit)
2021-06-27 21:25:29 +00:00
{
ViewContext *pContext;
2021-06-27 21:25:29 +00:00
if (!key.pContext)
2021-06-27 21:25:29 +00:00
{
AU_LOCK_GUARD(key.lock);
if (key.pContext)
{
pContext = (ViewContext *)key.pContext;
}
else
{
key.pContext = pContext = new ViewContext();
}
2021-06-27 21:25:29 +00:00
}
else
2021-06-27 21:25:29 +00:00
{
pContext = (ViewContext *)key.pContext;
2021-06-27 21:25:29 +00:00
}
auto &refEntry = pContext->GetHandleReference();
if (refEntry.pVoid)
2021-06-27 21:25:29 +00:00
{
return refEntry.pVoid;
2021-06-27 21:25:29 +00:00
}
else
2021-06-27 21:25:29 +00:00
{
refEntry.pVoid = AuMemory::_FAlloc(length, 64);
SysAssert(refEntry.pVoid, "TLS allocation failure");
2021-06-27 21:25:29 +00:00
if (init)
{
init(refEntry.pVoid);
}
refEntry.deinit = deinit;
return refEntry.pVoid;
2021-06-27 21:25:29 +00:00
}
}
void TLSView::Remove(TLSKey &key)
2021-06-27 21:25:29 +00:00
{
if (key.pContext)
2021-06-27 21:25:29 +00:00
{
delete (ViewContext *)key.pContext;
2021-06-27 21:25:29 +00:00
}
}
}