1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 20:12:21 +02:00
Beef/BeefLibs/corlib/src/Threading/Thread.bf

395 lines
11 KiB
Beef
Raw Normal View History

2019-08-23 11:56:54 -07:00
namespace System.Threading
{
using System;
using System.Diagnostics;
public delegate Object InternalCrossContextDelegate(Object[] args);
2019-08-23 11:56:54 -07:00
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(Object obj);
[StaticInitPriority(100)]
2019-08-23 11:56:54 -07:00
public sealed class Thread
{
private int mInternalThread;
2021-06-19 12:35:29 -07:00
private ThreadPriority mPriority = .Normal;
2019-08-23 11:56:54 -07:00
public int32 mMaxStackSize;
private String mName ~ delete _;
private Delegate mDelegate;
private Object mThreadStartArg;
bool mAutoDelete;
public static Thread sMainThread = new Thread() ~ delete _;
[StaticInitPriority(102)]
2019-08-23 11:56:54 -07:00
struct RuntimeThreadInit
{
static Object Thread_Alloc()
{
return Thread.CreateEmptyThread();
2019-08-23 11:56:54 -07:00
}
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)
{
if (internalThread != null)
GC.[Friend]AddPendingThread(internalThread);
2019-08-23 11:56:54 -07:00
((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);
2021-06-19 12:35:29 -07:00
if (thread.mPriority != .Normal)
thread.SetPriorityNative((.)thread.mPriority);
2019-08-23 11:56:54 -07:00
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.[Friend]sCallbacks;
2019-08-23 11:56:54 -07:00
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;
}
}
2020-01-25 07:03:14 -08:00
private this()
{
}
2019-08-23 11:56:54 -07:00
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 void Init()
2019-08-23 11:56:54 -07:00
{
#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
2019-08-23 11:56:54 -07:00
[CLink]
static extern int32 _tls_index;
#endif
public static int ModuleTLSIndex
{
get
{
#if BF_PLATFORM_WINDOWS
2019-08-23 11:56:54 -07:00
return _tls_index;
#else
return 0;
#endif
}
}
public void Suspend() { SuspendInternal(); }
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
private extern void SuspendInternal();
public void Resume() { ResumeInternal(); }
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
private extern void ResumeInternal();
public void Interrupt() { InterruptInternal(); }
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
private extern void InterruptInternal();
public ThreadPriority Priority
{
2021-06-19 12:35:29 -07:00
get
{
if (mInternalThread != 0)
return (ThreadPriority)GetPriorityNative();
return mPriority;
}
set
{
mPriority = value;
if (mInternalThread != 0)
SetPriorityNative((int32)value);
}
2019-08-23 11:56:54 -07:00
}
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
private extern int32 GetPriorityNative();
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
private extern void SetPriorityNative(int32 priority);
extern bool GetIsAlive();
public bool IsAlive
{
get
{
return GetIsAlive();
}
}
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
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();
}
}
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
private static extern Thread GetCurrentThreadNative();
void SetStart(Delegate ownStartDelegate, int32 maxStackSize)
2019-08-23 11:56:54 -07:00
{
mDelegate = ownStartDelegate;
2019-08-23 11:56:54 -07:00
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;
}
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
private extern void InternalFinalize();
public bool IsBackground
{
get { return IsBackgroundNative(); }
set { SetBackgroundNative(value); }
}
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
private extern bool IsBackgroundNative();
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
private extern void SetBackgroundNative(bool isBackground);
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
public extern void SetJoinOnDelete(bool joinOnDelete);
public ThreadState ThreadState
{
get { return (ThreadState)GetThreadStateNative(); }
}
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
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);
}
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
private extern void InformThreadNameChange(String name);
}
}