4 using System.Collections.Generic;
6 using System.Runtime.ExceptionServices;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using SiliconStudio.Core.Collections;
10 using SiliconStudio.Core.Diagnostics;
12 namespace SiliconStudio.Core.MicroThreading
22 internal static Logger Log = GlobalLogger.GetLogger(
"Scheduler");
25 internal long SchedulerCounter;
27 internal PriorityNodeQueue<MicroThread> scheduledMicroThreads =
new PriorityNodeQueue<MicroThread>();
28 internal LinkedList<MicroThread> allMicroThreads =
new LinkedList<MicroThread>();
30 private ThreadLocal<MicroThread> runningMicroThread =
new ThreadLocal<MicroThread>();
43 FrameChannel =
new Channel<int> { Preference = ChannelPreference.PreferSender };
52 get {
return runningMicroThread.Value; }
63 var currentThread = CurrentMicroThread;
64 return (currentThread != null) ? currentThread.Scheduler : null;
74 get {
return allMicroThreads; }
77 protected Channel<int> FrameChannel {
get;
private set; }
88 return (microThreadSyncContext != null) ? microThreadSyncContext.MicroThread : null;
110 throw new Exception(
"NextFrame cannot be called out of the micro-thread context.");
112 return FrameChannel.Receive();
121 #if SILICONSTUDIO_PLATFORM_WINDOWS_RUNTIME
122 int managedThreadId = 0;
124 int managedThreadId = Thread.CurrentThread.ManagedThreadId;
131 lock (scheduledMicroThreads)
133 if (scheduledMicroThreads.Count == 0)
135 microThread = scheduledMicroThreads.Dequeue();
137 callback = microThread.Callback;
138 microThread.Callback = null;
142 var previousRunningMicrothread = runningMicroThread.Value;
143 if (previousRunningMicrothread != null)
145 if (MicroThreadCallbackEnd != null)
149 runningMicroThread.Value = microThread;
150 var previousSyncContext = SynchronizationContext.Current;
151 SynchronizationContext.SetSynchronizationContext(microThread.SynchronizationContext);
157 if (MicroThreadCallbackStart != null)
160 using (Profiler.Begin(microThread.ProfilingKey))
167 Log.Error(
"Unexpected exception while executing a micro-thread", e);
168 microThread.SetException(e);
172 if (MicroThreadCallbackEnd != null)
175 SynchronizationContext.SetSynchronizationContext(previousSyncContext);
178 lock (microThread.AllLinkedListNode)
180 if (microThread.CompletionTask != null)
183 microThread.CompletionTask.TrySetException(microThread.Exception);
185 microThread.CompletionTask.TrySetResult(1);
193 ExceptionDispatchInfo.Capture(microThread.
Exception).Throw();
196 if (MicroThreadEnded != null)
201 runningMicroThread.Value = previousRunningMicrothread;
202 if (previousRunningMicrothread != null)
204 if (MicroThreadCallbackStart != null)
210 while (FrameChannel.Balance < 0)
211 FrameChannel.Send(0);
224 microThread.Start(microThreadFunction);
244 var currentMicroThread = CurrentMicroThread;
246 var tcs =
new TaskCompletionSource<int>();
256 throw new AggregateException(microThreads.Select(x => x.Exception).Where(x => x != null));
258 var completionTasks =
new List<Task<int>>();
259 foreach (var thread
in microThreads)
263 lock (thread.AllLinkedListNode)
265 if (thread.CompletionTask == null)
266 thread.CompletionTask =
new TaskCompletionSource<int>();
272 continuationTasks = completionTasks.ToArray();
275 await Task.Factory.ContinueWhenAll(continuationTasks, tasks => Task.WaitAll(tasks));
EventHandler< SchedulerThreadEventArgs > MicroThreadEnded
EventHandler< SchedulerThreadEventArgs > MicroThreadCallbackStart
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
ChannelMicroThreadAwaiter< int > NextFrame()
Yields execution until next frame.
MicroThread Add(Func< Task > microThreadFunction, MicroThreadFlags flags=MicroThreadFlags.None)
Creates a micro thread out of the specified function and schedules it as last micro thread to run in ...
System.Threading.Tasks.Task Task
Base implementation for ILogger.
Exception Exception
Gets the exception that was thrown by this MicroThread.
void Run()
Runs until no runnable tasklets left. This function is reentrant.
static MicroThread Current
Gets the current micro thread (self).
Scheduler()
Initializes a new instance of the Scheduler class.
MicroThreadFlags Flags
Gets the MicroThread flags.
MicroThread Create()
Creates a new empty micro thread, that could later be started with MicroThread.Start.
async Task WhenAll(params MicroThread[] microThreads)
Task that will completes when all MicroThread executions are completed.
EventHandler< SchedulerThreadEventArgs > MicroThreadCallbackEnd
Scheduler that manage a group of cooperating MicroThread.
MicroThreadState State
Gets the state of this MicroThread.
static MicroThreadYieldAwaiter Yield()
Yields execution. If any other micro thread is pending, it will be run now and current micro thread w...
EventHandler< SchedulerThreadEventArgs > MicroThreadStarted
Provides data for the Scheduler.MicroThreadStarted, Scheduler.MicroThreadEnded, Scheduler.MicroThreadCallbackStart and Scheduler.MicroThreadCallbackEnd events.
Output message to log right away.
bool IsOver
Indicates whether the MicroThread is terminated or not, either in Completed, Cancelled or Failed stat...