mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-19 00:20:25 +02:00

Throwing error on member references with ".." cascade token outside invocations (ie: "ts..mA = 123") Fixed 'Thread.ModuleTLSIndex' error - which caused us TLS lookup failures in Beef DLLs Fixed some hotswap errors Made BeefPerf shut down properly Fixed an 'int literal' FixIntUnknown issue where rhs was System.Object which caused an illegal boxing Fixed COFF::LocateSymbol issues with Win32 and also with linking to static libraries - showed up with hot-linking in fmod when hot-adding a floating point mod Fixed a couple memory leaks Fixed alignment issue in COFF::ParseCompileUnit
364 lines
9.8 KiB
Beef
364 lines
9.8 KiB
Beef
namespace System.Threading
|
|
{
|
|
using System;
|
|
using System.Diagnostics;
|
|
|
|
internal delegate Object InternalCrossContextDelegate(Object[] args);
|
|
|
|
public delegate void ThreadStart();
|
|
public delegate void ParameterizedThreadStart(Object obj);
|
|
|
|
public sealed class Thread
|
|
{
|
|
private int mInternalThread;
|
|
private int32 mPriority;
|
|
public int32 mMaxStackSize;
|
|
private String mName ~ delete _;
|
|
private Delegate mDelegate;
|
|
|
|
private Object mThreadStartArg;
|
|
|
|
bool mAutoDelete;
|
|
public static Thread sMainThread = new Thread() ~ delete _;
|
|
|
|
[StaticInitPriority(101)]
|
|
struct RuntimeThreadInit
|
|
{
|
|
static Object Thread_Alloc()
|
|
{
|
|
return Thread.[Friend]CreateEmptyThread();
|
|
}
|
|
|
|
static Object Thread_GetMainThread()
|
|
{
|
|
return Thread.[Friend]sMainThread;
|
|
}
|
|
|
|
static void* Thread_GetInternalThread(Object thread)
|
|
{
|
|
return (void*)((Thread)thread).[Friend]mInternalThread;
|
|
}
|
|
|
|
static void Thread_SetInternalThread(Object thread, void* internalThread)
|
|
{
|
|
((Thread)thread).[Friend]mInternalThread = (int)internalThread;
|
|
}
|
|
|
|
static bool Thread_IsAutoDelete(Object thread)
|
|
{
|
|
return ((Thread)thread).[Friend]mAutoDelete;
|
|
}
|
|
|
|
static void Thread_AutoDelete(Object thread)
|
|
{
|
|
delete thread;
|
|
}
|
|
|
|
static int32 Thread_GetMaxStackSize(Object thread)
|
|
{
|
|
return ((Thread)thread).mMaxStackSize;
|
|
}
|
|
|
|
static void Thread_StartProc(Object threadObj)
|
|
{
|
|
Thread thread = (Thread)threadObj;
|
|
|
|
if (thread.mName != null)
|
|
thread.InformThreadNameChange(thread.mName);
|
|
|
|
int32 stackStart = 0;
|
|
thread.SetStackStart((void*)&stackStart);
|
|
if (thread.mDelegate is ThreadStart)
|
|
{
|
|
((ThreadStart)thread.mDelegate)();
|
|
}
|
|
else
|
|
{
|
|
((ParameterizedThreadStart)thread.mDelegate)(thread.mThreadStartArg);
|
|
}
|
|
}
|
|
|
|
public static this()
|
|
{
|
|
var cb = ref Runtime.BfRtCallbacks.sCallbacks;
|
|
|
|
cb.[Friend]mThread_Alloc = => Thread_Alloc;
|
|
cb.[Friend]mThread_GetMainThread = => Thread_GetMainThread;
|
|
cb.[Friend]mThread_ThreadProc = => Thread_StartProc;
|
|
cb.[Friend]mThread_GetInternalThread = => Thread_GetInternalThread;
|
|
cb.[Friend]mThread_SetInternalThread = => Thread_SetInternalThread;
|
|
cb.[Friend]mThread_IsAutoDelete = => Thread_IsAutoDelete;
|
|
cb.[Friend]mThread_AutoDelete = => Thread_AutoDelete;
|
|
cb.[Friend]mThread_GetMaxStackSize = => Thread_GetMaxStackSize;
|
|
}
|
|
}
|
|
|
|
public this(ThreadStart start)
|
|
{
|
|
if (start == null)
|
|
{
|
|
Runtime.FatalError();
|
|
}
|
|
SetStart((Delegate)start, 0); //0 will setup Thread with default stackSize
|
|
}
|
|
|
|
public this(ThreadStart start, int32 maxStackSize)
|
|
{
|
|
if (start == null)
|
|
{
|
|
Runtime.FatalError();
|
|
}
|
|
if (0 > maxStackSize)
|
|
Runtime.FatalError();
|
|
SetStart((Delegate)start, maxStackSize);
|
|
}
|
|
|
|
public this(ParameterizedThreadStart start)
|
|
{
|
|
if (start == null)
|
|
{
|
|
Runtime.FatalError();
|
|
}
|
|
SetStart((Delegate)start, 0);
|
|
}
|
|
|
|
public this(ParameterizedThreadStart start, int32 maxStackSize)
|
|
{
|
|
if (start == null)
|
|
{
|
|
Runtime.FatalError();
|
|
}
|
|
if (0 > maxStackSize)
|
|
Runtime.FatalError();
|
|
SetStart((Delegate)start, maxStackSize);
|
|
}
|
|
|
|
static this()
|
|
{
|
|
#unwarn
|
|
RuntimeThreadInit runtimeThreadInitRef = ?;
|
|
sMainThread.ManualThreadInit();
|
|
}
|
|
|
|
static Thread CreateEmptyThread()
|
|
{
|
|
return new Thread();
|
|
}
|
|
|
|
public bool AutoDelete
|
|
{
|
|
set
|
|
{
|
|
// Changing AutoDelete from another thread while we are running is a race condition
|
|
Runtime.Assert((CurrentThread == this) || (!IsAlive));
|
|
mAutoDelete = value;
|
|
}
|
|
|
|
get
|
|
{
|
|
return mAutoDelete;
|
|
}
|
|
}
|
|
|
|
extern void ManualThreadInit();
|
|
extern void StartInternal();
|
|
extern void SetStackStart(void* ptr);
|
|
|
|
public void Start(bool autoDelete = true)
|
|
{
|
|
mAutoDelete = autoDelete;
|
|
StartInternal();
|
|
}
|
|
|
|
public void Start(Object parameter, bool autoDelete = true)
|
|
{
|
|
mAutoDelete = autoDelete;
|
|
if (mDelegate is ThreadStart)
|
|
{
|
|
Runtime.FatalError();
|
|
}
|
|
mThreadStartArg = parameter;
|
|
StartInternal();
|
|
}
|
|
|
|
#if BF_PLATFORM_WINDOWS
|
|
[CLink]
|
|
static extern int32 _tls_index;
|
|
#endif
|
|
|
|
public static int ModuleTLSIndex
|
|
{
|
|
get
|
|
{
|
|
#if BF_PLATFORM_WINDOWS
|
|
return _tls_index;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
public void Suspend() { SuspendInternal(); }
|
|
private extern void SuspendInternal();
|
|
|
|
public void Resume() { ResumeInternal(); }
|
|
private extern void ResumeInternal();
|
|
|
|
public void Interrupt() { InterruptInternal(); }
|
|
private extern void InterruptInternal();
|
|
|
|
public ThreadPriority Priority
|
|
{
|
|
get { return (ThreadPriority)GetPriorityNative(); }
|
|
set { SetPriorityNative((int32)value); }
|
|
}
|
|
private extern int32 GetPriorityNative();
|
|
private extern void SetPriorityNative(int32 priority);
|
|
|
|
extern bool GetIsAlive();
|
|
public bool IsAlive
|
|
{
|
|
get
|
|
{
|
|
return GetIsAlive();
|
|
}
|
|
}
|
|
|
|
extern bool GetIsThreadPoolThread();
|
|
public bool IsThreadPoolThread
|
|
{
|
|
get
|
|
{
|
|
return GetIsThreadPoolThread();
|
|
}
|
|
}
|
|
|
|
private extern bool JoinInternal(int32 millisecondsTimeout);
|
|
|
|
public void Join()
|
|
{
|
|
JoinInternal(Timeout.Infinite);
|
|
}
|
|
|
|
public bool Join(int32 millisecondsTimeout)
|
|
{
|
|
return JoinInternal(millisecondsTimeout);
|
|
}
|
|
|
|
public bool Join(TimeSpan timeout)
|
|
{
|
|
int64 tm = (int64)timeout.TotalMilliseconds;
|
|
if (tm < -1 || tm > (int64)Int32.MaxValue)
|
|
Runtime.FatalError();
|
|
|
|
return Join((int32)tm);
|
|
}
|
|
|
|
private static extern void SleepInternal(int32 millisecondsTimeout);
|
|
public static void Sleep(int32 millisecondsTimeout)
|
|
{
|
|
SleepInternal(millisecondsTimeout);
|
|
}
|
|
|
|
public static void Sleep(TimeSpan timeout)
|
|
{
|
|
int64 tm = (int64)timeout.TotalMilliseconds;
|
|
if (tm < -1 || tm > (int64)Int32.MaxValue)
|
|
Runtime.FatalError();
|
|
Sleep((int32)tm);
|
|
}
|
|
|
|
private static extern void SpinWaitInternal(int32 iterations);
|
|
|
|
public static void SpinWait(int iterations)
|
|
{
|
|
SpinWaitInternal((int32)iterations);
|
|
}
|
|
|
|
private static extern bool YieldInternal();
|
|
|
|
public static bool Yield()
|
|
{
|
|
return YieldInternal();
|
|
}
|
|
|
|
public static Thread CurrentThread
|
|
{
|
|
get
|
|
{
|
|
return GetCurrentThreadNative();
|
|
}
|
|
}
|
|
|
|
extern int32 GetThreadId();
|
|
|
|
public int32 Id
|
|
{
|
|
get
|
|
{
|
|
return GetThreadId();
|
|
}
|
|
}
|
|
|
|
private static extern Thread GetCurrentThreadNative();
|
|
|
|
void SetStart(Delegate start, int32 maxStackSize)
|
|
{
|
|
mDelegate = start;
|
|
mMaxStackSize = maxStackSize;
|
|
}
|
|
|
|
|
|
public ~this()
|
|
{
|
|
// Make sure we're not deleting manually it mAutoDelete is set
|
|
Debug.Assert((!mAutoDelete) || (CurrentThread == this));
|
|
// Delegate to the unmanaged portion.
|
|
InternalFinalize();
|
|
// Thread owns delegate
|
|
delete mDelegate;
|
|
}
|
|
|
|
private extern void InternalFinalize();
|
|
|
|
public bool IsBackground
|
|
{
|
|
get { return IsBackgroundNative(); }
|
|
set { SetBackgroundNative(value); }
|
|
}
|
|
private extern bool IsBackgroundNative();
|
|
private extern void SetBackgroundNative(bool isBackground);
|
|
|
|
public extern void SetJoinOnDelete(bool joinOnDelete);
|
|
|
|
public ThreadState ThreadState
|
|
{
|
|
get { return (ThreadState)GetThreadStateNative(); }
|
|
}
|
|
|
|
private extern int32 GetThreadStateNative();
|
|
|
|
public void SetName(String name)
|
|
{
|
|
if (name == null)
|
|
{
|
|
delete mName;
|
|
mName = null;
|
|
}
|
|
else
|
|
{
|
|
String.NewOrSet!(mName, name);
|
|
}
|
|
if (mInternalThread != 0)
|
|
InformThreadNameChange(name);
|
|
}
|
|
|
|
public void GetName(String outName)
|
|
{
|
|
if (mName != null)
|
|
outName.Append(mName);
|
|
}
|
|
|
|
private extern void InformThreadNameChange(String name);
|
|
}
|
|
}
|