4 using System.Collections.Generic;
5 using System.Diagnostics;
6 using System.Threading;
7 using System.Threading.Tasks;
8 using SiliconStudio.Core.Collections;
9 using SiliconStudio.Core.Diagnostics;
11 namespace SiliconStudio.Core.MicroThreading
25 private static long globalCounterId;
27 private class CallbackFromActionBuilder
29 public Action MicroThreadAction {
private get; set; }
31 public Action MicroThreadCallback {
get;
private set; }
33 public CallbackFromActionBuilder(
MicroThread microThread)
35 MicroThreadCallback = () =>
37 microThread.ThrowIfExceptionRequest();
39 microThread.ThrowIfExceptionRequest();
43 private class CallbackSendPostCallbackBuilder
45 public SendOrPostCallback SendOrPostCallback {
private get; set; }
46 public object CallbackState {
private get; set; }
48 public Action MicroThreadCallback {
get;
private set; }
50 public CallbackSendPostCallbackBuilder(MicroThread microThread)
52 MicroThreadCallback = () =>
54 microThread.ThrowIfExceptionRequest();
55 SendOrPostCallback(CallbackState);
56 microThread.ThrowIfExceptionRequest();
63 private long schedulerCounter;
66 internal PriorityQueueNode<MicroThread> ScheduledLinkedListNode;
67 internal LinkedListNode<MicroThread> AllLinkedListNode;
68 internal Action Callback;
71 private readonly CallbackFromActionBuilder callbackFromActionBuilder;
72 private readonly CallbackSendPostCallbackBuilder callbackSendPostCallbackBuilder;
76 Id = Interlocked.Increment(ref globalCounterId);
78 ScheduledLinkedListNode =
new PriorityQueueNode<MicroThread>(
this);
79 AllLinkedListNode =
new LinkedListNode<MicroThread>(
this);
84 callbackFromActionBuilder =
new CallbackFromActionBuilder(
this);
85 callbackSendPostCallbackBuilder =
new CallbackSendPostCallbackBuilder(
this);
96 get {
return priority; }
97 set { priority = value; }
106 public long Id {
get;
private set; }
114 public string Name {
get; set; }
155 internal Exception ExceptionToRaise {
get; set; }
160 internal TaskCompletionSource<int> CompletionTask {
get; set; }
170 State == MicroThreadState.Completed ||
171 State == MicroThreadState.Cancelled ||
172 State == MicroThreadState.Failed;
182 get {
return Scheduler.CurrentMicroThread; }
187 var priorityDiff = priority.CompareTo(other.priority);
188 if (priorityDiff != 0)
191 return schedulerCounter.CompareTo(other.schedulerCounter);
196 throw new NotImplementedException();
201 throw new NotImplementedException();
217 throw new InvalidOperationException(
"MicroThread was already started before.");
219 Action wrappedMicroThreadFunction = async () =>
223 State = MicroThreadState.Running;
225 await microThreadFunction();
228 throw new InvalidOperationException(
"MicroThread completed in an invalid state.");
229 State = MicroThreadState.Completed;
233 Scheduler.Log.Error(
"Unexpected exception while executing a micro-thread. Reason: {0}",
new object[] {e});
240 Scheduler.allMicroThreads.Remove(AllLinkedListNode);
245 Action callback = () =>
250 wrappedMicroThreadFunction();
255 Scheduler.allMicroThreads.AddLast(AllLinkedListNode);
258 ScheduleContinuation(scheduleMode, callback);
268 var currentScheduler = Scheduler.Current;
270 await Scheduler.Yield();
282 if (ExceptionToRaise == null)
283 ExceptionToRaise = e;
286 internal void SetException(
Exception exception)
296 lock (Scheduler.scheduledMicroThreads)
298 if (ScheduledLinkedListNode.Index != -1)
300 Scheduler.scheduledMicroThreads.Remove(ScheduledLinkedListNode);
302 Schedule(scheduleMode);
307 internal void ScheduleContinuation(
ScheduleMode scheduleMode, SendOrPostCallback callback,
object callbackState)
309 Debug.Assert(callback != null);
310 lock (Scheduler.scheduledMicroThreads)
312 callbackSendPostCallbackBuilder.SendOrPostCallback = callback;
313 callbackSendPostCallbackBuilder.CallbackState = callbackState;
314 Callback += callbackSendPostCallbackBuilder.MicroThreadCallback;
316 if (ScheduledLinkedListNode.Index != -1)
317 throw new InvalidOperationException(
"MicroThread was already scheduled, something is probably wrong.");
319 Schedule(scheduleMode);
323 internal void ScheduleContinuation(
ScheduleMode scheduleMode, Action callback)
325 Debug.Assert(callback != null);
326 lock (Scheduler.scheduledMicroThreads)
328 callbackFromActionBuilder.MicroThreadAction = callback;
329 Callback += callbackFromActionBuilder.MicroThreadCallback;
331 if (ScheduledLinkedListNode.Index != -1)
332 throw new InvalidOperationException(
"MicroThread was already scheduled, something is probably wrong.");
334 Schedule(scheduleMode);
340 var nextCounter = Scheduler.SchedulerCounter++;
342 nextCounter = -nextCounter;
344 schedulerCounter = nextCounter;
346 Scheduler.scheduledMicroThreads.Enqueue(ScheduledLinkedListNode);
349 internal void ThrowIfExceptionRequest()
351 if (ExceptionToRaise != null)
352 throw ExceptionToRaise;
A key to identify a specific profile.
Represents an execution context managed by a Scheduler, that can cooperatively yield execution to ano...
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ DXGI_FORMAT _In_ DWORD flags
MicroThread(Scheduler scheduler, MicroThreadFlags flags=MicroThreadFlags.None)
void RaiseException(Exception e)
Raises an exception from within the MicroThread.
Represents a container that can hold properties, lightweight to embed (lazy initialized).
PropertyContainer Tags
Gets the attached properties to this component.
Flags
Enumeration of the new Assimp's flags.
int CompareTo(MicroThread other)
async Task Run()
Yields to this MicroThread.
Scheduler that manage a group of cooperating MicroThread.
void Start(Func< Task > microThreadFunction, ScheduleMode scheduleMode=ScheduleMode.Last)
Starts this MicroThread with the specified function.
void Migrate(Scheduler scheduler)