/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: TLSView.cpp Date: 2021-6-12 Author: Reece ***/ #include #include "TLSView.hpp" namespace Aurora::Threading::Threads { void TLSViewImpl::Remove(AuUInt64 key) { LockGuard 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 re(&lock_); std::pair*value; if (!length) { return nullptr; } if (!TryFind(tls_, key, value)) { if (noAutoCreate) { return nullptr; } auto buf = Memory::ZAlloc(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 re(&lock_); std::pair*value; if (!length) { return nullptr; } if (TryFind(tls_, key, value)) { return value->first; } auto buf = Memory::ZAlloc(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 (...) { } } }