139 lines
2.8 KiB
C++
139 lines
2.8 KiB
C++
|
/***
|
||
|
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||
|
|
||
|
File: TLSView.cpp
|
||
|
Date: 2021-6-12
|
||
|
Author: Reece
|
||
|
***/
|
||
|
#include <RuntimeInternal.hpp>
|
||
|
#include "TLSView.hpp"
|
||
|
|
||
|
namespace Aurora::Threading::Threads
|
||
|
{
|
||
|
void TLSViewImpl::Remove(AuUInt64 key)
|
||
|
{
|
||
|
LockGuard<Primitives::SpinLock> re(&lock_);
|
||
|
|
||
|
auto a = tls_.find(key);
|
||
|
if (a == tls_.end())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const auto &handler = a->second.second;
|
||
|
if (handler)
|
||
|
{
|
||
|
handler(a->second.first);
|
||
|
}
|
||
|
|
||
|
tls_.erase(a);
|
||
|
}
|
||
|
|
||
|
TLSViewImpl::~TLSViewImpl()
|
||
|
{
|
||
|
for (const auto &itr : tls_)
|
||
|
{
|
||
|
const auto &handler = itr.second.second;
|
||
|
if (handler)
|
||
|
{
|
||
|
handler(itr.second.first);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
tls_.clear();
|
||
|
}
|
||
|
|
||
|
void *TLSViewImpl::GetTLS(AuUInt64 key, AuMach length, bool noAutoCreate)
|
||
|
{
|
||
|
LockGuard<Primitives::SpinLock> re(&lock_);
|
||
|
std::pair<void*, TlsCb>*value;
|
||
|
|
||
|
if (!length)
|
||
|
{
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
if (!TryFind(tls_, key, value))
|
||
|
{
|
||
|
if (noAutoCreate)
|
||
|
{
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
auto buf = Memory::ZAlloc<void *>(length);
|
||
|
if (!buf)
|
||
|
{
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
auto ok = TryInsertNoEnd(tls_, std::make_pair(key, std::make_pair(buf, TlsCb {})));
|
||
|
if (!ok)
|
||
|
{
|
||
|
Memory::Free(buf);
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
ConsiderRehash();
|
||
|
|
||
|
return buf;
|
||
|
}
|
||
|
|
||
|
return value->first;
|
||
|
}
|
||
|
|
||
|
void *TLSViewImpl::InitTLS(AuUInt64 key, AuMach length, const TlsCb &init, const TlsCb &deinit)
|
||
|
{
|
||
|
LockGuard<Primitives::SpinLock> re(&lock_);
|
||
|
std::pair<void*, TlsCb>*value;
|
||
|
|
||
|
if (!length)
|
||
|
{
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
if (TryFind(tls_, key, value))
|
||
|
{
|
||
|
return value->first;
|
||
|
}
|
||
|
|
||
|
auto buf = Memory::ZAlloc<void *>(length);
|
||
|
if (!buf)
|
||
|
{
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
TlsCb deinitcb = deinit;
|
||
|
auto ok = TryInsertNoEnd(tls_, std::make_pair(key, std::make_pair(buf, deinitcb)));
|
||
|
if (!ok)
|
||
|
{
|
||
|
Memory::Free(buf);
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
ConsiderRehash();
|
||
|
|
||
|
if (init)
|
||
|
{
|
||
|
init(buf);
|
||
|
}
|
||
|
|
||
|
return buf;
|
||
|
}
|
||
|
|
||
|
void TLSViewImpl::ConsiderRehash()
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
// prevent Add, Remove, Add, Remove stalls
|
||
|
fence_++;
|
||
|
if ((fence_ % 10) == 0)
|
||
|
{
|
||
|
tls_.rehash(tls_.size());
|
||
|
}
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|