Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -61,7 +64,7 @@ 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 after dueTime.
Expand All @@ -77,32 +80,69 @@ public override IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Fun
if (action == null)
throw new ArgumentNullException(nameof(action));

var dt = Time + Scheduler.Normalize(dueTime);

var si = new ScheduledItem<TimeSpan, TState>(this, state, action, dt);

var queue = GetQueue();
var queue = default(SchedulerQueue<TimeSpan>);

if (queue == null)
// There is no timed task and no task is currently running
if (!running)
{
queue = new SchedulerQueue<TimeSpan>(4);
queue.Enqueue(si);
running = true;

SetQueue(queue);
if (dueTime > TimeSpan.Zero)
{
ConcurrencyAbstractionLayer.Current.Sleep(dueTime);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can we omit the normalization of dueTime here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public void Sleep(TimeSpan timeout) => System.Threading.Thread.Sleep(Normalize(timeout));

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't mind if it is negative and Sleep will normalize it anyway.

}

// execute directly without queueing
IDisposable d;
try
{
Trampoline.Run(queue);
d = action(this, state);
}
finally
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;
}
else

queue = GetQueue();

// if there is a task running or there is a queue
if (queue == null)
{
queue.Enqueue(si);
queue = new SchedulerQueue<TimeSpan>(4);
SetQueue(queue);
}

var dt = Time + Scheduler.Normalize(dueTime);

// queue up more work
var si = new ScheduledItem<TimeSpan, TState>(this, state, action, dt);
queue.Enqueue(si);
return si;
}

Expand Down