blob: 3f5f47f1ec5ce5624ce0d1791aba3eee88242dac [file]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#pragma once
class ThreadContextTLSEntry
{
public:
static bool InitializeProcess();
static void CleanupProcess();
static bool IsProcessInitialized();
static void InitializeThread();
static void CleanupThread();
static void Delete(ThreadContextTLSEntry * entry);
static bool TrySetThreadContext(ThreadContext * threadContext);
static void SetThreadContext(ThreadContextTLSEntry * entry, ThreadContext * threadContext);
static bool ClearThreadContext(bool isValid);
static bool ClearThreadContext(ThreadContextTLSEntry * entry, bool isThreadContextValid, bool force = true);
static ThreadContextTLSEntry * GetEntryForCurrentThread();
static ThreadContextTLSEntry * CreateEntryForCurrentThread();
static ThreadContextId GetThreadContextId(ThreadContext * threadContext);
#ifdef _WIN32
static uint32 s_tlsSlot;
#endif
ThreadContext * GetThreadContext();
private:
friend JsUtil::ExternalApi;
static ThreadContextId GetCurrentThreadContextId();
private:
ThreadContext * threadContext;
StackProber prober;
};
class ThreadContextScope
{
public:
ThreadContextScope(ThreadContext * threadContext)
{
if (!threadContext->IsThreadBound())
{
originalContext = ThreadContextTLSEntry::GetEntryForCurrentThread() ?
ThreadContextTLSEntry::GetEntryForCurrentThread()->GetThreadContext() : NULL;
wasInUse = threadContext == originalContext;
isValid = ThreadContextTLSEntry::TrySetThreadContext(threadContext);
doCleanup = !wasInUse && isValid;
}
else
{
Assert(ThreadContext::GetContextForCurrentThread() == threadContext);
isValid = true;
wasInUse = true;
doCleanup = false;
}
}
~ThreadContextScope()
{
if (doCleanup)
{
bool cleared = true;
#if DBG
cleared =
#endif
ThreadContextTLSEntry::ClearThreadContext(this->isValid);
Assert(cleared);
if (originalContext)
{
bool canSetback = true;
#if DBG
canSetback =
#endif
ThreadContextTLSEntry::TrySetThreadContext(originalContext);
Assert(canSetback);
}
}
}
void Invalidate()
{
this->isValid = false;
}
bool IsValid() const
{
return this->isValid;
}
bool WasInUse() const
{
return this->wasInUse;
}
private:
bool doCleanup;
bool isValid;
bool wasInUse;
ThreadContext* originalContext;
};