mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Lazy<T>
, LazyTLS<T>
, thread dtors
This commit is contained in:
parent
cf269db0eb
commit
a27ef9beda
17 changed files with 437 additions and 30 deletions
288
BeefLibs/corlib/src/Lazy.bf
Normal file
288
BeefLibs/corlib/src/Lazy.bf
Normal file
|
@ -0,0 +1,288 @@
|
|||
using System.Threading;
|
||||
|
||||
namespace System
|
||||
{
|
||||
enum LazyThreadMode
|
||||
{
|
||||
None,
|
||||
Lock,
|
||||
Lockless
|
||||
}
|
||||
|
||||
class Lazy<T>
|
||||
{
|
||||
protected struct Entry
|
||||
{
|
||||
public SelfOuter mSingleton;
|
||||
public T mValue;
|
||||
}
|
||||
|
||||
protected Monitor mMonitor ~ delete _;
|
||||
protected LazyThreadMode mThreadMode;
|
||||
protected volatile int mInitId;
|
||||
protected T mValue;
|
||||
delegate T() mCreateDlg ~ delete _;
|
||||
delegate void(T value) mReleaseDlg ~ delete _;
|
||||
|
||||
public this()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public this(LazyThreadMode threadMode)
|
||||
{
|
||||
mThreadMode = threadMode;
|
||||
Init();
|
||||
}
|
||||
|
||||
public this(LazyThreadMode threadMode, delegate T() createDlg = null, delegate void(T value) releaseDlg = null)
|
||||
{
|
||||
mThreadMode = threadMode;
|
||||
mCreateDlg = createDlg;
|
||||
mReleaseDlg = releaseDlg;
|
||||
Init();
|
||||
}
|
||||
|
||||
public this(delegate void(T value) releaseDlg) : this()
|
||||
{
|
||||
mReleaseDlg = releaseDlg;
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
switch (mThreadMode)
|
||||
{
|
||||
case .None:
|
||||
case .Lock:
|
||||
mMonitor = new Monitor();
|
||||
case .Lockless:
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
ReleaseValue(mut mValue);
|
||||
}
|
||||
|
||||
protected T DefaultCreateValue()
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
protected T DefaultCreateValue() where T : struct, new
|
||||
{
|
||||
return T();
|
||||
}
|
||||
|
||||
protected T DefaultCreateValue() where T : class
|
||||
{
|
||||
Runtime.FatalError("No create delegate specified and no public default constructor is available");
|
||||
}
|
||||
|
||||
protected T DefaultCreateValue() where T : class, new
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
|
||||
protected virtual T CreateValue()
|
||||
{
|
||||
return DefaultCreateValue();
|
||||
}
|
||||
|
||||
protected void DefaultReleaseValue(mut T val)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected void DefaultReleaseValue(mut T val) where T : struct, IDisposable
|
||||
{
|
||||
val.Dispose();
|
||||
}
|
||||
|
||||
protected void DefaultReleaseValue(mut T val) where T : class
|
||||
{
|
||||
delete (Object)val;
|
||||
}
|
||||
|
||||
protected virtual void ReleaseValue(mut T val)
|
||||
{
|
||||
DefaultReleaseValue(mut val);
|
||||
}
|
||||
|
||||
public ref T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (mInitId == -1)
|
||||
return ref mValue;
|
||||
|
||||
switch (mThreadMode)
|
||||
{
|
||||
case .None:
|
||||
mValue = CreateValue();
|
||||
case .Lock:
|
||||
using (mMonitor.Enter())
|
||||
{
|
||||
if (mInitId != -1)
|
||||
{
|
||||
mValue = CreateValue();
|
||||
Interlocked.Fence();
|
||||
mInitId = -1;
|
||||
}
|
||||
}
|
||||
case .Lockless:
|
||||
int threadId = Thread.CurrentThreadId;
|
||||
while (true)
|
||||
{
|
||||
int initId = Interlocked.CompareExchange(ref mInitId, 0, threadId);
|
||||
if (initId == -1)
|
||||
break;
|
||||
|
||||
if (initId == 0)
|
||||
{
|
||||
Interlocked.Fence();
|
||||
mValue = CreateValue();
|
||||
Interlocked.Fence();
|
||||
mInitId = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ref mValue;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsValueCreated => mInitId != 0;
|
||||
|
||||
public static ref T operator->(Self self) => ref self.[Inline]Value;
|
||||
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
if (IsValueCreated)
|
||||
strBuffer.AppendF($"Value: {Value}");
|
||||
else
|
||||
strBuffer.AppendF($"No Value");
|
||||
}
|
||||
}
|
||||
|
||||
class LazyTLS<T>
|
||||
{
|
||||
protected struct Entry
|
||||
{
|
||||
public SelfOuter mSingleton;
|
||||
public T mValue;
|
||||
}
|
||||
|
||||
void* mData;
|
||||
delegate T() mCreateDlg ~ delete _;
|
||||
delegate void(T value) mReleaseDlg ~ delete _;
|
||||
|
||||
public this()
|
||||
{
|
||||
InitTLS();
|
||||
}
|
||||
|
||||
public this(delegate T() createDlg = null, delegate void(T value) releaseDlg = null)
|
||||
{
|
||||
mCreateDlg = createDlg;
|
||||
mReleaseDlg = releaseDlg;
|
||||
InitTLS();
|
||||
}
|
||||
|
||||
void InitTLS()
|
||||
{
|
||||
mData = Platform.BfpTLS_Create((ptr) =>
|
||||
{
|
||||
var entry = (Entry*)ptr;
|
||||
if (entry.mSingleton.mReleaseDlg != null)
|
||||
entry.mSingleton.mReleaseDlg(entry.mValue);
|
||||
else
|
||||
entry.mSingleton.ReleaseValue(mut entry.mValue);
|
||||
delete entry;
|
||||
});
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
Platform.BfpTLS_Release((.)mData);
|
||||
}
|
||||
|
||||
protected T DefaultCreateValue()
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
protected T DefaultCreateValue() where T : struct, new
|
||||
{
|
||||
return T();
|
||||
}
|
||||
|
||||
protected T DefaultCreateValue() where T : class
|
||||
{
|
||||
Runtime.FatalError("No create delegate specified and no public default constructor is available");
|
||||
}
|
||||
|
||||
protected T DefaultCreateValue() where T : class, new
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
|
||||
protected virtual T CreateValue()
|
||||
{
|
||||
return DefaultCreateValue();
|
||||
}
|
||||
|
||||
protected void DefaultReleaseValue(mut T val)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected void DefaultReleaseValue(mut T val) where T : struct, IDisposable
|
||||
{
|
||||
val.Dispose();
|
||||
}
|
||||
|
||||
|
||||
protected void DefaultReleaseValue(mut T val) where T : class
|
||||
{
|
||||
delete (Object)val;
|
||||
}
|
||||
|
||||
protected virtual void ReleaseValue(mut T val)
|
||||
{
|
||||
DefaultReleaseValue(mut val);
|
||||
}
|
||||
|
||||
public ref T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
void* ptr = Platform.BfpTLS_GetValue((.)mData);
|
||||
if (ptr != null)
|
||||
return ref ((Entry*)ptr).mValue;
|
||||
|
||||
Entry* entry = new Entry();
|
||||
entry.mSingleton = this;
|
||||
if (mCreateDlg != null)
|
||||
entry.mValue = mCreateDlg();
|
||||
else
|
||||
entry.mValue = CreateValue();
|
||||
Platform.BfpTLS_SetValue((.)mData, entry);
|
||||
return ref entry.mValue;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsValueCreated => Platform.BfpTLS_GetValue((.)mData) != null;
|
||||
|
||||
public static ref T operator->(Self self) => ref self.[Inline]Value;
|
||||
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
if (IsValueCreated)
|
||||
strBuffer.AppendF($"Value: {Value}");
|
||||
else
|
||||
strBuffer.AppendF($"No Value");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -42,6 +42,7 @@ namespace System
|
|||
public struct BfpEvent {};
|
||||
public struct BfpFileWatcher {}
|
||||
public struct BfpProcess {}
|
||||
public struct BfpTLS;
|
||||
|
||||
public enum BfpSystemResult : int32
|
||||
{
|
||||
|
@ -95,6 +96,18 @@ namespace System
|
|||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern void BfpSystem_GetComputerName(char8* outStr, int32* inOutStrSize, BfpSystemResult* outResult);
|
||||
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern int BfpThread_GetCurrentId();
|
||||
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern BfpTLS* BfpTLS_Create(function [CallingConvention(.Stdcall)] void(void*) exitProc);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern void BfpTLS_Release(BfpTLS* tls);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern void BfpTLS_SetValue(BfpTLS* tls, void* value);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern void* BfpTLS_GetValue(BfpTLS* tls);
|
||||
|
||||
public enum BfpFileWatcherFlags : int32
|
||||
{
|
||||
None = 0,
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace System
|
|||
[StaticInitPriority(101)]
|
||||
static class Runtime
|
||||
{
|
||||
const int32 cVersion = 9;
|
||||
const int32 cVersion = 10;
|
||||
|
||||
[CRepr, AlwaysInclude]
|
||||
struct BfDebugMessageData
|
||||
|
@ -118,6 +118,7 @@ namespace System
|
|||
function bool (Object thread) mThread_IsAutoDelete;
|
||||
function void (Object thread) mThread_AutoDelete;
|
||||
function int32 (Object thread) mThread_GetMaxStackSize;
|
||||
function void () mThread_Exiting;
|
||||
function void () mGC_MarkAllStaticMembers;
|
||||
function bool () mGC_CallRootCallbacks;
|
||||
function void () mGC_Shutdown;
|
||||
|
|
|
@ -20,8 +20,13 @@ namespace System.Threading
|
|||
private Object mThreadStartArg;
|
||||
|
||||
bool mAutoDelete;
|
||||
public static Thread sMainThread = new Thread() ~ delete _;
|
||||
|
||||
|
||||
static Monitor sMonitor = new .() ~ delete _;
|
||||
static Event<delegate void()> sOnExit ~ _.Dispose();
|
||||
Event<delegate void()> mOnExit ~ _.Dispose();
|
||||
|
||||
public static Thread sMainThread = new Thread() ~ delete _;
|
||||
|
||||
[StaticInitPriority(102)]
|
||||
struct RuntimeThreadInit
|
||||
{
|
||||
|
@ -62,6 +67,14 @@ namespace System.Threading
|
|||
return ((Thread)thread).mMaxStackSize;
|
||||
}
|
||||
|
||||
static void Thread_Exiting()
|
||||
{
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
sOnExit();
|
||||
}
|
||||
}
|
||||
|
||||
static void Thread_StartProc(Object threadObj)
|
||||
{
|
||||
Thread thread = (Thread)threadObj;
|
||||
|
@ -103,6 +116,7 @@ namespace System.Threading
|
|||
cb.[Friend]mThread_IsAutoDelete = => Thread_IsAutoDelete;
|
||||
cb.[Friend]mThread_AutoDelete = => Thread_AutoDelete;
|
||||
cb.[Friend]mThread_GetMaxStackSize = => Thread_GetMaxStackSize;
|
||||
cb.[Friend]mThread_Exiting = => Thread_Exiting;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,6 +192,38 @@ namespace System.Threading
|
|||
}
|
||||
}
|
||||
|
||||
public void AddExitNotify(delegate void() dlg)
|
||||
{
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
mOnExit.Add(dlg);
|
||||
}
|
||||
}
|
||||
|
||||
public Result<void> RemovedExitNotify(delegate void() dlg, bool delegateDelegate = false)
|
||||
{
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
return mOnExit.Remove(dlg, delegateDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddGlobalExitNotify(delegate void() dlg)
|
||||
{
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
sOnExit.Add(dlg);
|
||||
}
|
||||
}
|
||||
|
||||
public static Result<void> RemoveGlobalExitNotify(delegate void() dlg, bool delegateDelegate = false)
|
||||
{
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
return sOnExit.Remove(dlg, delegateDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
extern void ManualThreadInit();
|
||||
extern void StartInternal();
|
||||
extern void SetStackStart(void* ptr);
|
||||
|
@ -217,6 +263,7 @@ namespace System.Threading
|
|||
}
|
||||
}
|
||||
|
||||
public static extern void RequestExitNotify();
|
||||
public extern void Suspend();
|
||||
public extern void Resume();
|
||||
|
||||
|
@ -316,9 +363,10 @@ namespace System.Threading
|
|||
}
|
||||
}
|
||||
|
||||
extern int32 GetThreadId();
|
||||
[CallingConvention(.Cdecl)]
|
||||
extern int GetThreadId();
|
||||
|
||||
public int32 Id
|
||||
public int Id
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -326,6 +374,8 @@ namespace System.Threading
|
|||
}
|
||||
}
|
||||
|
||||
public static int CurrentThreadId => Platform.BfpThread_GetCurrentId();
|
||||
|
||||
[CallingConvention(.Cdecl)]
|
||||
private static extern Thread GetCurrentThreadNative();
|
||||
|
||||
|
@ -337,6 +387,12 @@ namespace System.Threading
|
|||
|
||||
public ~this()
|
||||
{
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
mOnExit();
|
||||
sOnExit();
|
||||
}
|
||||
|
||||
// Make sure we're not deleting manually if mAutoDelete is set
|
||||
Debug.Assert((!mAutoDelete) || (CurrentThread == this));
|
||||
// Delegate to the unmanaged portion.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "BeefySysLib/Common.h"
|
||||
#include "BeefySysLib/util/String.h"
|
||||
|
||||
#define BFRT_VERSION 9
|
||||
#define BFRT_VERSION 10
|
||||
|
||||
#ifdef BFRT_DYNAMIC
|
||||
#define BFRT_EXPORT __declspec(dllexport)
|
||||
|
@ -99,6 +99,7 @@ namespace bf
|
|||
bool(*Thread_IsAutoDelete)(bf::System::Threading::Thread* thread);
|
||||
void(*Thread_AutoDelete)(bf::System::Threading::Thread* thread);
|
||||
int32(*Thread_GetMaxStackSize)(bf::System::Threading::Thread* thread);
|
||||
void(*Thread_Exiting)();
|
||||
void(*GC_MarkAllStaticMembers)();
|
||||
bool(*GC_CallRootCallbacks)();
|
||||
void(*GC_Shutdown)();
|
||||
|
@ -107,7 +108,7 @@ namespace bf
|
|||
void(*DebugMessageData_SetupProfilerCmd)(const char* str);
|
||||
void(*DebugMessageData_Fatal)();
|
||||
void(*DebugMessageData_Clear)();
|
||||
int(*CheckErrorHandler)(const char* kind, const char* arg1, const char* arg2, intptr arg3);
|
||||
int(*CheckErrorHandler)(const char* kind, const char* arg1, const char* arg2, intptr arg3);
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
|
@ -55,6 +55,12 @@ static Beefy::StringT<0> gCmdLineString;
|
|||
bf::System::Runtime::BfRtCallbacks gBfRtCallbacks;
|
||||
BfRtFlags gBfRtFlags = (BfRtFlags)0;
|
||||
|
||||
#ifdef BF_PLATFORM_WINDOWS
|
||||
DWORD gBfTLSKey = 0;
|
||||
#else
|
||||
pthread_key_t gBfTLSKey = 0;
|
||||
#endif
|
||||
|
||||
static int gTestMethodIdx = -1;
|
||||
static uint32 gTestStartTick = 0;
|
||||
static bool gTestBreakOnFailure = false;
|
||||
|
@ -287,6 +293,11 @@ static void GetCrashInfo()
|
|||
}
|
||||
}
|
||||
|
||||
static void NTAPI TlsFreeFunc(void* ptr)
|
||||
{
|
||||
gBfRtCallbacks.Thread_Exiting();
|
||||
}
|
||||
|
||||
void bf::System::Runtime::Init(int version, int flags, BfRtCallbacks* callbacks)
|
||||
{
|
||||
BfpSystemInitFlags sysInitFlags = BfpSystemInitFlag_InstallCrashCatcher;
|
||||
|
@ -343,6 +354,12 @@ void bf::System::Runtime::Init(int version, int flags, BfRtCallbacks* callbacks)
|
|||
useCmdLineStr++;
|
||||
}
|
||||
gCmdLineString = useCmdLineStr;
|
||||
|
||||
#ifdef BF_PLATFORM_WINDOWS
|
||||
gBfTLSKey = FlsAlloc(TlsFreeFunc);
|
||||
#else
|
||||
pthread_key_create(&gBfTLSKey, TlsFreeFunc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void bf::System::Runtime::SetErrorString(char* errorStr)
|
||||
|
|
|
@ -19,6 +19,12 @@ BF_TLS_DECLSPEC Thread* Thread::sCurrentThread;
|
|||
static volatile int gLiveThreadCount;
|
||||
static Beefy::SyncEvent gThreadsDoneEvent;
|
||||
|
||||
#ifdef BF_PLATFORM_WINDOWS
|
||||
extern DWORD gBfTLSKey;
|
||||
#else
|
||||
extern pthread_key_t gBfTLSKey;
|
||||
#endif
|
||||
|
||||
bf::System::Threading::Thread* BfGetCurrentThread()
|
||||
{
|
||||
#ifdef BF_THREAD_TLS
|
||||
|
@ -133,7 +139,8 @@ static void BF_CALLTYPE CStartProc(void* threadParam)
|
|||
bool wantsDelete = false;
|
||||
//
|
||||
{
|
||||
internalThread->ThreadStopped();
|
||||
internalThread->ThreadStopped();
|
||||
|
||||
Beefy::AutoCrit autoCrit(internalThread->mCritSect);
|
||||
if (isAutoDelete)
|
||||
gBfRtCallbacks.Thread_AutoDelete(thread);
|
||||
|
@ -207,15 +214,28 @@ void Thread::StartInternal()
|
|||
#endif
|
||||
}
|
||||
|
||||
void Thread::RequestExitNotify()
|
||||
{
|
||||
// Do we already have implicit exiting notification?
|
||||
if (BfGetCurrentThread() != NULL)
|
||||
return;
|
||||
|
||||
#ifdef BF_PLATFORM_WINDOWS
|
||||
FlsSetValue(gBfTLSKey, (void*)&gBfRtCallbacks);
|
||||
#else
|
||||
pthread_setspecific(gBfTLSKey, (void*)&gBfRtCallbacks);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Thread::ThreadStarted()
|
||||
{
|
||||
auto internalThread = GetInternalThread();
|
||||
internalThread->mCritSect.Unlock();
|
||||
}
|
||||
|
||||
int Thread::GetThreadId()
|
||||
intptr Thread::GetThreadId()
|
||||
{
|
||||
return (int)GetInternalThread()->mThreadId;
|
||||
return GetInternalThread()->mThreadId;
|
||||
}
|
||||
|
||||
void Thread::SetStackStart(void* ptr)
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace bf
|
|||
private:
|
||||
BfInternalThread* SetupInternalThread();
|
||||
|
||||
BFRT_EXPORT void ManualThreadInit();
|
||||
BFRT_EXPORT void ManualThreadInit();
|
||||
BFRT_EXPORT int GetPriorityNative();
|
||||
BFRT_EXPORT void SetPriorityNative(int priority);
|
||||
BFRT_EXPORT void SetJoinOnDelete(bool joinOnDelete);
|
||||
|
@ -59,7 +59,7 @@ namespace bf
|
|||
BFRT_EXPORT void SetBackgroundNative(bool isBackground);
|
||||
BFRT_EXPORT int GetThreadStateNative();
|
||||
BFRT_EXPORT void InformThreadNameChange(String* name);
|
||||
BFRT_EXPORT int GetThreadId();
|
||||
BFRT_EXPORT intptr GetThreadId();
|
||||
|
||||
BFRT_EXPORT void Dbg_CreateInternal();
|
||||
|
||||
|
@ -68,6 +68,7 @@ namespace bf
|
|||
BFRT_EXPORT void Resume();
|
||||
BFRT_EXPORT void Abort();
|
||||
|
||||
BFRT_EXPORT static void RequestExitNotify();
|
||||
BFRT_EXPORT static void MemoryBarrier();
|
||||
|
||||
static Thread* Alloc()
|
||||
|
|
|
@ -35,7 +35,7 @@ uint32 BfTLSManager::Alloc()
|
|||
}
|
||||
}
|
||||
|
||||
mAllocatedKeys[idx] = BfpTLS_Create();
|
||||
mAllocatedKeys[idx] = BfpTLS_Create(NULL);
|
||||
mAssociatedTLSDatums[idx] = NULL;
|
||||
return idx;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
|
||||
BfTLSManager()
|
||||
{
|
||||
sInternalThreadKey = BfpTLS_Create();
|
||||
sInternalThreadKey = BfpTLS_Create(NULL);
|
||||
mAssociatedTLSDatums = NULL;
|
||||
mAllocSize = 0;
|
||||
mAllocIdx = 1;
|
||||
|
|
|
@ -223,6 +223,7 @@ enum BfpThreadCreateFlags
|
|||
};
|
||||
|
||||
typedef void (BFP_CALLTYPE *BfpThreadStartProc)(void* threadParam);
|
||||
typedef void (BFP_CALLTYPE* BfpTLSProc)(void* threadParam);
|
||||
|
||||
enum BfpThreadPriority
|
||||
{
|
||||
|
@ -273,8 +274,9 @@ BFP_EXPORT void BFP_CALLTYPE BfpCritSect_Enter(BfpCritSect* critSect);
|
|||
BFP_EXPORT bool BFP_CALLTYPE BfpCritSect_TryEnter(BfpCritSect* critSect, int waitMS);
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpCritSect_Leave(BfpCritSect* critSect);
|
||||
|
||||
|
||||
struct BfpTLS;
|
||||
BFP_EXPORT BfpTLS* BFP_CALLTYPE BfpTLS_Create();
|
||||
BFP_EXPORT BfpTLS* BFP_CALLTYPE BfpTLS_Create(BfpTLSProc exitProc);
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpTLS_Release(BfpTLS* tls);
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpTLS_SetValue(BfpTLS* tls, void* value);
|
||||
BFP_EXPORT void* BFP_CALLTYPE BfpTLS_GetValue(BfpTLS* tls);
|
||||
|
|
|
@ -1528,10 +1528,10 @@ BFP_EXPORT void BFP_CALLTYPE BfpCritSect_Leave(BfpCritSect* critSect)
|
|||
pthread_mutex_unlock(&critSect->mPMutex);
|
||||
}
|
||||
|
||||
BFP_EXPORT BfpTLS* BFP_CALLTYPE BfpTLS_Create()
|
||||
BFP_EXPORT BfpTLS* BFP_CALLTYPE BfpTLS_Create(BfpTLSProc exitProc)
|
||||
{
|
||||
pthread_key_t key = 0;
|
||||
pthread_key_create(&key, NULL);
|
||||
pthread_key_create(&key, exitProc);
|
||||
return (BfpTLS*)(intptr)key;
|
||||
}
|
||||
|
||||
|
|
|
@ -2530,24 +2530,24 @@ BFP_EXPORT void BFP_CALLTYPE BfpCritSect_Leave(BfpCritSect* critSect)
|
|||
#define BFPTLS_TO_DWORD(val) ((DWORD)(intptr)(val))
|
||||
|
||||
struct BfpTLS;
|
||||
BFP_EXPORT BfpTLS* BFP_CALLTYPE BfpTLS_Create()
|
||||
BFP_EXPORT BfpTLS* BFP_CALLTYPE BfpTLS_Create(BfpTLSProc exitProc)
|
||||
{
|
||||
return DWORD_TO_BFPTLS(::TlsAlloc());
|
||||
return DWORD_TO_BFPTLS(::FlsAlloc(exitProc));
|
||||
}
|
||||
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpTLS_Release(BfpTLS* tls)
|
||||
{
|
||||
::TlsFree(BFPTLS_TO_DWORD(tls));
|
||||
::FlsFree(BFPTLS_TO_DWORD(tls));
|
||||
}
|
||||
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpTLS_SetValue(BfpTLS* tls, void* value)
|
||||
{
|
||||
::TlsSetValue(BFPTLS_TO_DWORD(tls), value);
|
||||
::FlsSetValue(BFPTLS_TO_DWORD(tls), value);
|
||||
}
|
||||
|
||||
BFP_EXPORT void* BFP_CALLTYPE BfpTLS_GetValue(BfpTLS* tls)
|
||||
{
|
||||
return ::TlsGetValue(BFPTLS_TO_DWORD(tls));
|
||||
return ::FlsGetValue(BFPTLS_TO_DWORD(tls));
|
||||
}
|
||||
|
||||
BFP_EXPORT BfpEvent* BFP_CALLTYPE BfpEvent_Create(BfpEventFlags flags)
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace System.Diagnostics
|
|||
}
|
||||
}
|
||||
|
||||
static Result<ProfileId> StartSampling(int32 threadId, StringView profileDesc)
|
||||
static Result<ProfileId> StartSampling(int threadId, StringView profileDesc)
|
||||
{
|
||||
//int32 curId = Interlocked.Increment(ref gProfileId);
|
||||
int32 curId = gProfileId++;
|
||||
|
|
|
@ -95,7 +95,7 @@ namespace System
|
|||
|
||||
extension Result<T> where T : IDisposable
|
||||
{
|
||||
public void Dispose()
|
||||
public new void Dispose()
|
||||
{
|
||||
if (this case .Ok(var val))
|
||||
val.Dispose();
|
||||
|
@ -199,7 +199,7 @@ namespace System
|
|||
|
||||
extension Result<T, TErr> where T : IDisposable
|
||||
{
|
||||
public void Dispose()
|
||||
public new void Dispose()
|
||||
{
|
||||
if (this case .Ok(var val))
|
||||
val.Dispose();
|
||||
|
@ -208,7 +208,7 @@ namespace System
|
|||
|
||||
extension Result<T, TErr> where TErr : IDisposable
|
||||
{
|
||||
public void Dispose()
|
||||
public new void Dispose()
|
||||
{
|
||||
if (this case .Err(var err))
|
||||
err.Dispose();
|
||||
|
@ -217,7 +217,7 @@ namespace System
|
|||
|
||||
extension Result<T, TErr> where T : IDisposable where TErr : IDisposable
|
||||
{
|
||||
public void Dispose()
|
||||
public new void Dispose()
|
||||
{
|
||||
if (this case .Ok(var val))
|
||||
val.Dispose();
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace System
|
|||
[StaticInitPriority(100)]
|
||||
class Runtime
|
||||
{
|
||||
const int32 cVersion = 9;
|
||||
const int32 cVersion = 10;
|
||||
|
||||
[CRepr, AlwaysInclude]
|
||||
struct BfDebugMessageData
|
||||
|
@ -116,6 +116,7 @@ namespace System
|
|||
function bool (Object thread) mThread_IsAutoDelete;
|
||||
function void (Object thread) mThread_AutoDelete;
|
||||
function int32 (Object thread) mThread_GetMaxStackSize;
|
||||
function void () mThread_Exiting;
|
||||
function void () mGC_MarkAllStaticMembers;
|
||||
function bool () mGC_CallRootCallbacks;
|
||||
function void () mGC_Shutdown;
|
||||
|
|
|
@ -78,6 +78,11 @@ namespace System.Threading
|
|||
}
|
||||
}
|
||||
|
||||
static void Thread_Exiting()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static this()
|
||||
{
|
||||
var cb = ref Runtime.BfRtCallbacks.[Friend]sCallbacks;
|
||||
|
@ -90,6 +95,7 @@ namespace System.Threading
|
|||
cb.[Friend]mThread_IsAutoDelete = => Thread_IsAutoDelete;
|
||||
cb.[Friend]mThread_AutoDelete = => Thread_AutoDelete;
|
||||
cb.[Friend]mThread_GetMaxStackSize = => Thread_GetMaxStackSize;
|
||||
cb.[Friend]mThread_Exiting = => Thread_Exiting;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,9 +286,10 @@ namespace System.Threading
|
|||
}
|
||||
}
|
||||
|
||||
extern int32 GetThreadId();
|
||||
[CallingConvention(.Cdecl)]
|
||||
extern int GetThreadId();
|
||||
|
||||
public int32 Id
|
||||
public int Id
|
||||
{
|
||||
get
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue