mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-18 08:06:04 +02:00
Initial checkin
This commit is contained in:
parent
c74712dad9
commit
078564ac9e
3242 changed files with 1616395 additions and 0 deletions
182
BeefLibs/corlib/src/System/Threading/ThreadPool.bf
Normal file
182
BeefLibs/corlib/src/System/Threading/ThreadPool.bf
Normal file
|
@ -0,0 +1,182 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
|
||||
//#define DISABLE_THREADS
|
||||
|
||||
namespace System.Threading
|
||||
{
|
||||
public delegate void WorkDelegate();
|
||||
|
||||
enum WorkEntry
|
||||
{
|
||||
case WorkDelegate(WorkDelegate callback);
|
||||
case WorkItem(IThreadPoolWorkItem workItem);
|
||||
}
|
||||
|
||||
struct ThreadStats
|
||||
{
|
||||
public volatile int32 mCount;
|
||||
public volatile int32 mMax;
|
||||
public volatile int32 mActive;
|
||||
}
|
||||
|
||||
internal interface IThreadPoolWorkItem
|
||||
{
|
||||
void ExecuteWorkItem();
|
||||
void MarkAborted();
|
||||
}
|
||||
|
||||
public static class ThreadPool
|
||||
{
|
||||
static int32 sConcurrency = 8;
|
||||
static bool sStarted = false;
|
||||
static List<Thread> sThreads = new List<Thread>() ~ delete _;
|
||||
static bool sShuttingDown;
|
||||
static Monitor sMonitor = new Monitor() ~ delete _;
|
||||
static Monitor sBindingMonitor = new Monitor() ~ delete _;
|
||||
static WaitEvent sThreadWakeEvent = new WaitEvent() ~ delete _;
|
||||
static WaitEvent sThreadClosedEvent = new WaitEvent() ~ delete _;
|
||||
|
||||
static ThreadStats sWorkerThreadStats;
|
||||
static ThreadStats sIOThreadStats;
|
||||
static List<WorkEntry> mWorkEntries = new List<WorkEntry>() ~ delete _;
|
||||
|
||||
static this()
|
||||
{
|
||||
//TODO: This is really bad, fix this pool!
|
||||
sWorkerThreadStats.mMax = 4;
|
||||
sIOThreadStats.mMax = 4;
|
||||
}
|
||||
|
||||
static ~this()
|
||||
{
|
||||
sShuttingDown = true;
|
||||
|
||||
while (true)
|
||||
{
|
||||
sThreadWakeEvent.Set(true);
|
||||
|
||||
using (sMonitor.Enter())
|
||||
if (sThreads.Count == 0)
|
||||
break;
|
||||
sThreadClosedEvent.WaitFor();
|
||||
}
|
||||
|
||||
//Console.WriteLine("ThreadPool.~this done");
|
||||
}
|
||||
|
||||
static void CheckSpawnWorkerThread()
|
||||
{
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
if ((sWorkerThreadStats.mActive == sWorkerThreadStats.mCount) && (sWorkerThreadStats.mCount < sWorkerThreadStats.mMax))
|
||||
{
|
||||
int threadId = sThreads.Count;
|
||||
sWorkerThreadStats.mCount++;
|
||||
sWorkerThreadStats.mActive++; // We know the thread will immediately become active
|
||||
|
||||
Thread thread = new Thread(new () => { WorkerProc(threadId); });
|
||||
sThreads.Add(thread);
|
||||
thread.Start(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool TryPopCustomWorkItem(WorkEntry workEntry)
|
||||
{
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
return mWorkEntries.Remove(workEntry);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryPopCustomWorkItem(IThreadPoolWorkItem workItem)
|
||||
{
|
||||
return TryPopCustomWorkItem(.WorkItem(workItem));
|
||||
}
|
||||
|
||||
public static bool QueueUserWorkItem(IThreadPoolWorkItem workItem)
|
||||
{
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
mWorkEntries.Add(.WorkItem(workItem));
|
||||
CheckSpawnWorkerThread();
|
||||
sThreadWakeEvent.Set();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool QueueUserWorkItem(WorkDelegate waitCallback)
|
||||
{
|
||||
#if DISABLE_THREADS
|
||||
waitCallback(userState);
|
||||
return true;
|
||||
#endif
|
||||
|
||||
Debug.AssertNotStack(waitCallback);
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
mWorkEntries.Add(.WorkDelegate(waitCallback));
|
||||
CheckSpawnWorkerThread();
|
||||
sThreadWakeEvent.Set();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int32 sBindCount = 0;
|
||||
public static int32 sReleaseBindCount = 0;
|
||||
|
||||
static void Start()
|
||||
{
|
||||
sStarted = true;
|
||||
}
|
||||
|
||||
static void ThreadDone()
|
||||
{
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
Thread currentThread = Thread.CurrentThread;
|
||||
sThreads.Remove(currentThread);
|
||||
delete currentThread;
|
||||
sThreadClosedEvent.Set();
|
||||
}
|
||||
}
|
||||
|
||||
static void WorkerProc(int id)
|
||||
{
|
||||
let threadName = scope String();
|
||||
threadName.AppendF("ThreadPool Worker {0}", id);
|
||||
Thread.CurrentThread.SetName(threadName);
|
||||
|
||||
while (true)
|
||||
{
|
||||
WorkEntry? workEntryOptional = null;
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
if (mWorkEntries.Count != 0)
|
||||
workEntryOptional = mWorkEntries.PopFront();
|
||||
}
|
||||
|
||||
if (!workEntryOptional.HasValue)
|
||||
{
|
||||
sThreadWakeEvent.WaitFor();
|
||||
if (sShuttingDown)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
var workEntry = workEntryOptional.Value;
|
||||
switch (workEntry)
|
||||
{
|
||||
case .WorkDelegate(let callback):
|
||||
callback();
|
||||
delete callback;
|
||||
case .WorkItem(let workItem):
|
||||
workItem.ExecuteWorkItem();
|
||||
}
|
||||
}
|
||||
ThreadDone();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue