-
Notifications
You must be signed in to change notification settings - Fork 782
4.x: CurrentThreadScheduler fast path Schedule #599
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
0df9e18
4135b4c
06baa29
960099f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,6 +31,9 @@ private CurrentThreadScheduler() | |
| [ThreadStatic] | ||
| private static IStopwatch s_clock; | ||
|
|
||
| [ThreadStatic] | ||
| private static bool running; | ||
|
|
||
| private static SchedulerQueue<TimeSpan> GetQueue() => s_threadLocalQueue; | ||
|
|
||
| private static void SetQueue(SchedulerQueue<TimeSpan> newQueue) | ||
|
|
@@ -61,7 +64,79 @@ private static TimeSpan Time | |
| /// Gets a value that indicates whether the caller must call a Schedule method. | ||
| /// </summary> | ||
| [EditorBrowsable(EditorBrowsableState.Advanced)] | ||
| public static bool IsScheduleRequired => GetQueue() == null; | ||
| public static bool IsScheduleRequired => !running; | ||
|
|
||
| /// <summary> | ||
| /// Schedules an action to be executed immediately. | ||
| /// </summary> | ||
| /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam> | ||
| /// <param name="state">State passed to the action to be executed.</param> | ||
| /// <param name="action">Action to be executed.</param> | ||
| /// <returns>The disposable object used to cancel the scheduled action (best effort).</returns> | ||
| /// <exception cref="ArgumentNullException"><paramref name="action"/> is <c>null</c>.</exception> | ||
| public override IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action) | ||
| { | ||
| if (action == null) | ||
| throw new ArgumentNullException(nameof(action)); | ||
|
|
||
| var queue = default(SchedulerQueue<TimeSpan>); | ||
|
|
||
| // There is no timed task and no task is currently running | ||
| if (!running) | ||
| { | ||
| running = true; | ||
|
|
||
| // execute directly without queueing | ||
| IDisposable d; | ||
| try | ||
| { | ||
| d = action(this, state); | ||
| } | ||
| catch | ||
| { | ||
| SetQueue(null); | ||
| running = false; | ||
| throw; | ||
| } | ||
|
|
||
| // did recursive tasks arrive? | ||
| queue = GetQueue(); | ||
|
|
||
| // yes, run those in the queue as well | ||
| if (queue != null) | ||
| { | ||
| try | ||
| { | ||
| Trampoline.Run(queue); | ||
| } | ||
| finally | ||
| { | ||
| SetQueue(null); | ||
| running = false; | ||
| } | ||
| } | ||
| else | ||
| { | ||
| running = false; | ||
| } | ||
|
|
||
| return d; | ||
| } | ||
|
|
||
| queue = GetQueue(); | ||
|
|
||
| // if there is a task running or there is a queue | ||
| if (queue == null) | ||
| { | ||
| queue = new SchedulerQueue<TimeSpan>(4); | ||
| SetQueue(queue); | ||
| } | ||
|
|
||
| // queue up more work | ||
| var si = new ScheduledItem<TimeSpan, TState>(this, state, action, Time); | ||
| queue.Enqueue(si); | ||
| return si; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Schedules an action to be executed after dueTime. | ||
|
|
@@ -86,22 +161,23 @@ public override IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Fun | |
| if (queue == null) | ||
| { | ||
| queue = new SchedulerQueue<TimeSpan>(4); | ||
| queue.Enqueue(si); | ||
|
|
||
| SetQueue(queue); | ||
| } | ||
| queue.Enqueue(si); | ||
|
|
||
| if (!running) | ||
| { | ||
| running = true; | ||
| try | ||
| { | ||
| Trampoline.Run(queue); | ||
| } | ||
| finally | ||
| { | ||
| SetQueue(null); | ||
|
||
| running = false; | ||
| } | ||
| } | ||
| else | ||
| { | ||
| queue.Enqueue(si); | ||
| } | ||
|
|
||
| return si; | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you pack it into the timed overload for the dueTime == 0 case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe. I'm trying to avoid the time arithmetic overhead.