mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-17 15:46:05 +02:00
Moving corlib files out of "System" directory into root
This commit is contained in:
parent
4cd58262e4
commit
7dbfd15292
179 changed files with 3 additions and 0 deletions
143
BeefLibs/corlib/src/Threading/Tasks/Future.bf
Normal file
143
BeefLibs/corlib/src/Threading/Tasks/Future.bf
Normal file
|
@ -0,0 +1,143 @@
|
|||
// This file contains portions of code released by Microsoft under the MIT license as part
|
||||
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
||||
// The original source was submitted to https://github.com/Microsoft/referencesource
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace System.Threading.Tasks
|
||||
{
|
||||
public class Task<TResult> : Task
|
||||
{
|
||||
internal TResult m_result; // The value itself, if set.
|
||||
protected bool mHasCompleted;
|
||||
protected int32 mRefCount = 1;
|
||||
|
||||
internal TResult ResultOnSuccess
|
||||
{
|
||||
get
|
||||
{
|
||||
//Contract.Assert(!IsWaitNotificationEnabledOrNotRanToCompletion, "Should only be used when the task completed successfully and there's no wait notification enabled");
|
||||
return m_result;
|
||||
}
|
||||
}
|
||||
|
||||
public TResult Result
|
||||
{
|
||||
get { return IsWaitNotificationEnabledOrNotRanToCompletion ? GetResultCore(true) : m_result; }
|
||||
}
|
||||
|
||||
public this(Func<Object, TResult> func, Object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
|
||||
: this(func, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken,
|
||||
creationOptions, InternalTaskOptions.None, null)
|
||||
{
|
||||
//StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
|
||||
//PossiblyCaptureContext(ref stackMark);
|
||||
}
|
||||
|
||||
internal this(Func<TResult> valueSelector, Task parent, CancellationToken cancellationToken,
|
||||
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
|
||||
base(valueSelector, null, parent, cancellationToken, creationOptions, internalOptions, scheduler)
|
||||
{
|
||||
if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
|
||||
{
|
||||
Runtime.FatalError();
|
||||
}
|
||||
}
|
||||
|
||||
internal this(Delegate valueSelector, Object state, Task parent, CancellationToken cancellationToken,
|
||||
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
|
||||
base(valueSelector, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
|
||||
{
|
||||
if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
|
||||
{
|
||||
Runtime.FatalError();
|
||||
}
|
||||
}
|
||||
|
||||
public new TaskAwaiter<TResult> GetAwaiter()
|
||||
{
|
||||
return TaskAwaiter<TResult>(this);
|
||||
}
|
||||
|
||||
public void Ref()
|
||||
{
|
||||
//Interlocked.Increment(ref mRefCount);
|
||||
mRefCount++;
|
||||
}
|
||||
|
||||
public void Deref()
|
||||
{
|
||||
//if (Interlocked.Decrement(ref mRefCount) == 1)
|
||||
|
||||
if (--mRefCount == 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Deref();
|
||||
}
|
||||
|
||||
// Implements Result. Result delegates to this method if the result isn't already available.
|
||||
internal TResult GetResultCore(bool waitCompletionNotification)
|
||||
{
|
||||
// If the result has not been calculated yet, wait for it.
|
||||
if (!IsCompleted) InternalWait(Timeout.Infinite, default(CancellationToken)); // won't throw if task faulted or canceled; that's handled below
|
||||
|
||||
// Notify the debugger of the wait completion if it's requested such a notification
|
||||
//TODO: Implement
|
||||
//if (waitCompletionNotification) NotifyDebuggerOfWaitCompletionIfNecessary();
|
||||
|
||||
// Throw an exception if appropriate.
|
||||
//TODO: ? if (!IsRanToCompletion) ThrowIfExceptional(true);
|
||||
|
||||
// We shouldn't be here if the result has not been set.
|
||||
//Contract.Assert(IsRanToCompletion, "Task<T>.Result getter: Expected result to have been set.");
|
||||
|
||||
return m_result;
|
||||
}
|
||||
|
||||
List<Action<Task<TResult>>> mContinuations = new List<Action<Task<TResult>>>() ~ delete _;
|
||||
|
||||
public Task ContinueWith(Action<Task<TResult>> continuationAction)
|
||||
{
|
||||
bool callDirectly = false;
|
||||
using (mMonitor.Enter())
|
||||
{
|
||||
if (!mHasCompleted)
|
||||
mContinuations.Add(continuationAction);
|
||||
else
|
||||
callDirectly = true;
|
||||
}
|
||||
if (callDirectly)
|
||||
{
|
||||
// The task has already completed, call directly
|
||||
Ref();
|
||||
continuationAction(this);
|
||||
Deref();
|
||||
}
|
||||
return null;
|
||||
//TODO: Not correct implementation
|
||||
//StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
|
||||
//return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
|
||||
}
|
||||
|
||||
public void Notify(bool allowDelete = true)
|
||||
{
|
||||
var continueList = scope List<Action<Task<TResult>>>(16);
|
||||
using (mMonitor.Enter())
|
||||
{
|
||||
mHasCompleted = true;
|
||||
for (var action in mContinuations)
|
||||
continueList.Add(action);
|
||||
}
|
||||
|
||||
Ref();
|
||||
for (var action in continueList)
|
||||
action(this);
|
||||
Deref();
|
||||
}
|
||||
}
|
||||
}
|
1405
BeefLibs/corlib/src/Threading/Tasks/Task.bf
Normal file
1405
BeefLibs/corlib/src/Threading/Tasks/Task.bf
Normal file
File diff suppressed because it is too large
Load diff
108
BeefLibs/corlib/src/Threading/Tasks/TaskScheduler.bf
Normal file
108
BeefLibs/corlib/src/Threading/Tasks/TaskScheduler.bf
Normal file
|
@ -0,0 +1,108 @@
|
|||
// This file contains portions of code released by Microsoft under the MIT license as part
|
||||
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
||||
// The original source was submitted to https://github.com/Microsoft/referencesource
|
||||
|
||||
namespace System.Threading.Tasks
|
||||
{
|
||||
abstract class TaskScheduler
|
||||
{
|
||||
private static readonly TaskScheduler s_defaultTaskScheduler = new ThreadPoolTaskScheduler() ~ delete _;
|
||||
|
||||
public static TaskScheduler Default
|
||||
{
|
||||
get
|
||||
{
|
||||
return s_defaultTaskScheduler;
|
||||
}
|
||||
}
|
||||
|
||||
public static TaskScheduler Current
|
||||
{
|
||||
get
|
||||
{
|
||||
TaskScheduler current = InternalCurrent;
|
||||
return current ?? TaskScheduler.Default;
|
||||
}
|
||||
}
|
||||
|
||||
internal static TaskScheduler InternalCurrent
|
||||
{
|
||||
get
|
||||
{
|
||||
Task currentTask = Task.InternalCurrent;
|
||||
return ( (currentTask != null)
|
||||
&& ((currentTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0)
|
||||
) ? currentTask.ExecutingTaskScheduler : null;
|
||||
}
|
||||
}
|
||||
|
||||
protected internal abstract void QueueTask(Task task);
|
||||
protected abstract bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the scheduler that a work item has made progress.
|
||||
/// </summary>
|
||||
internal virtual void NotifyWorkItemProgress()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal bool TryRunInline(Task task, bool taskWasPreviouslyQueued)
|
||||
{
|
||||
TaskScheduler ets = task.ExecutingTaskScheduler;
|
||||
|
||||
// Delegate cross-scheduler inlining requests to target scheduler
|
||||
if(ets != this && ets !=null) return ets.TryRunInline(task, taskWasPreviouslyQueued);
|
||||
|
||||
//StackGuard currentStackGuard;
|
||||
if( (ets == null) ||
|
||||
(task.m_action == null) ||
|
||||
task.IsDelegateInvoked ||
|
||||
task.IsCanceled
|
||||
//|| (currentStackGuard = Task.CurrentStackGuard).TryBeginInliningScope() == false
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Task class will still call into TaskScheduler.TryRunInline rather than TryExecuteTaskInline() so that
|
||||
// 1) we can adjust the return code from TryExecuteTaskInline in case a buggy custom scheduler lies to us
|
||||
// 2) we maintain a mechanism for the TLS lookup optimization that we used to have for the ConcRT scheduler (will potentially introduce the same for TP)
|
||||
bool bInlined = false;
|
||||
//try
|
||||
{
|
||||
task.FireTaskScheduledIfNeeded(this);
|
||||
bInlined = TryExecuteTaskInline(task, taskWasPreviouslyQueued);
|
||||
}
|
||||
/*finally
|
||||
{
|
||||
currentStackGuard.EndInliningScope();
|
||||
}*/
|
||||
|
||||
// If the custom scheduler returned true, we should either have the TASK_STATE_DELEGATE_INVOKED or TASK_STATE_CANCELED bit set
|
||||
// Otherwise the scheduler is buggy
|
||||
/*if (bInlined && !(task.IsDelegateInvoked || task.IsCanceled))
|
||||
{
|
||||
throw new InvalidOperationException(Environment.GetResourceString("TaskScheduler_InconsistentStateAfterTryExecuteTaskInline"));
|
||||
}*/
|
||||
|
||||
return bInlined;
|
||||
}
|
||||
|
||||
internal void InternalQueueTask(Task task)
|
||||
{
|
||||
//task.FireTaskScheduledIfNeeded(this);
|
||||
this.QueueTask(task);
|
||||
}
|
||||
|
||||
protected internal virtual bool TryDequeue(Task task)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
internal virtual bool RequiresAtomicStartTransition
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
}
|
107
BeefLibs/corlib/src/Threading/Tasks/ThreadPoolTaskScheduler.bf
Normal file
107
BeefLibs/corlib/src/Threading/Tasks/ThreadPoolTaskScheduler.bf
Normal file
|
@ -0,0 +1,107 @@
|
|||
// This file contains portions of code released by Microsoft under the MIT license as part
|
||||
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
||||
// The original source was submitted to https://github.com/Microsoft/referencesource
|
||||
|
||||
namespace System.Threading.Tasks
|
||||
{
|
||||
class ThreadPoolTaskScheduler : TaskScheduler
|
||||
{
|
||||
/// Constructs a new ThreadPool task scheduler object
|
||||
internal this()
|
||||
{
|
||||
}
|
||||
|
||||
// static delegate for threads allocated to handle LongRunning tasks.
|
||||
//private static readonly ParameterizedThreadStart s_longRunningThreadWork = new => LongRunningThreadWork;
|
||||
|
||||
private static void LongRunningThreadWork(Object obj)
|
||||
{
|
||||
//Contract.Requires(obj != null, "TaskScheduler.LongRunningThreadWork: obj is null");
|
||||
Task t = obj as Task;
|
||||
//Contract.Assert(t != null, "TaskScheduler.LongRunningThreadWork: t is null");
|
||||
t.ExecuteEntry(false);
|
||||
}
|
||||
|
||||
/// Schedules a task to the ThreadPool.
|
||||
/// @param task The task to schedule.
|
||||
protected internal override void QueueTask(Task task)
|
||||
{
|
||||
if ((task.Options & TaskCreationOptions.LongRunning) != 0)
|
||||
{
|
||||
// Run LongRunning tasks on their own dedicated thread.
|
||||
Thread thread = new Thread(new => LongRunningThreadWork);
|
||||
thread.IsBackground = true; // Keep this thread from blocking process shutdown
|
||||
thread.Start(task);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal handling for non-LongRunning tasks.
|
||||
//bool forceToGlobalQueue = ((task.Options & TaskCreationOptions.PreferFairness) != 0);
|
||||
ThreadPool.QueueUserWorkItem(task);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// This internal function will do this:
|
||||
/// (1) If the task had previously been queued, attempt to pop it and return false if that fails.
|
||||
/// (2) Propagate the return value from Task.ExecuteEntry() back to the caller.
|
||||
///
|
||||
/// IMPORTANT NOTE: TryExecuteTaskInline will NOT throw task exceptions itself. Any wait code path using this function needs
|
||||
/// to account for exceptions that need to be propagated, and throw themselves accordingly.
|
||||
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
|
||||
{
|
||||
// If the task was previously scheduled, and we can't pop it, then return false.
|
||||
if (taskWasPreviouslyQueued && !ThreadPool.TryPopCustomWorkItem(task))
|
||||
return false;
|
||||
|
||||
// Propagate the return value of Task.ExecuteEntry()
|
||||
bool rval = false;
|
||||
//try
|
||||
{
|
||||
rval = task.ExecuteEntry(false); // handles switching Task.Current etc.
|
||||
}
|
||||
/*finally
|
||||
{
|
||||
// Only call NWIP() if task was previously queued
|
||||
if(taskWasPreviouslyQueued) NotifyWorkItemProgress();
|
||||
}*/
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
protected internal override bool TryDequeue(Task task)
|
||||
{
|
||||
// just delegate to TP
|
||||
return ThreadPool.TryPopCustomWorkItem(task);
|
||||
}
|
||||
|
||||
/*protected override IEnumerable<Task> GetScheduledTasks()
|
||||
{
|
||||
return FilterTasksFromWorkItems(ThreadPool.GetQueuedWorkItems());
|
||||
}
|
||||
|
||||
private IEnumerable<Task> FilterTasksFromWorkItems(IEnumerable<IThreadPoolWorkItem> tpwItems)
|
||||
{
|
||||
for (IThreadPoolWorkItem tpwi in tpwItems)
|
||||
{
|
||||
if (tpwi is Task)
|
||||
{
|
||||
yield return (Task)tpwi;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/// Notifies the scheduler that work is progressing (no-op).
|
||||
internal override void NotifyWorkItemProgress()
|
||||
{
|
||||
//ThreadPool.NotifyWorkItemProgress();
|
||||
}
|
||||
|
||||
/// This is the only scheduler that returns false for this property, indicating that the task entry codepath is unsafe (CAS free)
|
||||
/// since we know that the underlying scheduler already takes care of atomic transitions from queued to non-queued.
|
||||
internal override bool RequiresAtomicStartTransition
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue