Skip to content

Commit

Permalink
Add FixedThreadsTaskScheduler.Name.
Browse files Browse the repository at this point in the history
  • Loading branch information
hamster620 committed Jan 15, 2024
1 parent 9335a31 commit 2d1ebe1
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 43 deletions.
4 changes: 2 additions & 2 deletions Core/Threading/Tasks/FixedThreadsTaskFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ public FixedThreadsTaskFactory(int maxConcurrencyLevel, bool useBackgroundThread
/// <summary>
/// Get number of threads which are executing tasks.
/// </summary>
public int BusyThreadCount { get => ((FixedThreadsTaskScheduler)this.Scheduler!).BusyThreadCount; }
public int BusyThreadCount => ((FixedThreadsTaskScheduler)this.Scheduler!).BusyThreadCount;


/// <summary>
/// Get maximum concurrency level supported by its <see cref="TaskFactory.Scheduler"/>.
/// </summary>
public int MaximumConcurrencyLevel { get => ((FixedThreadsTaskScheduler)this.Scheduler!).MaximumConcurrencyLevel; }
public int MaximumConcurrencyLevel => ((FixedThreadsTaskScheduler)this.Scheduler!).MaximumConcurrencyLevel;
}
}
72 changes: 31 additions & 41 deletions Core/Threading/Tasks/FixedThreadsTaskScheduler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,6 @@ namespace CarinaStudio.Threading.Tasks
/// </summary>
public class FixedThreadsTaskScheduler : TaskScheduler, IDisposable
{
// Synchronization context of scheduler.
class SyncContext : SynchronizationContext
{
// Fields.
readonly FixedThreadsTaskScheduler scheduler;

// Constructor.
public SyncContext(FixedThreadsTaskScheduler scheduler) =>
this.scheduler = scheduler;

/// <inheritdoc/>
public override SynchronizationContext CreateCopy() =>
new SyncContext(this.scheduler);

/// <inheritdoc/>
public override void Post(SendOrPostCallback d, object? state) =>
this.scheduler.QueueTask(new Task(() => d(state)));
}


// Static fields.
static volatile int LatestId;

Expand All @@ -40,23 +20,34 @@ public override void Post(SendOrPostCallback d, object? state) =>
readonly int id;
volatile bool isDisposed;
volatile int latestExecThreadId;
volatile int numberOfBusyThreads;
readonly LinkedList<Task> scheduledTasks = new LinkedList<Task>();
readonly object syncLock = new object();
int numberOfBusyThreads;
readonly LinkedList<Task> scheduledTasks = new();
readonly object syncLock = new();
readonly bool useBackgroundThreads;


/// <summary>
/// Initialize new <see cref="FixedThreadsTaskScheduler"/> instance.
/// </summary>
/// <param name="maxConcurrencyLevel">Maximum concurrency level.</param>
/// <param name="useBackgroundThreads">True to set execution threads as background thread.</param>
public FixedThreadsTaskScheduler(int maxConcurrencyLevel, bool useBackgroundThreads = true) : this(null, maxConcurrencyLevel, useBackgroundThreads)
{ }


/// <summary>
/// Initialize new <see cref="FixedThreadsTaskScheduler"/> instance.
/// </summary>
/// <param name="name">Name of scheduler.</param>
/// <param name="maxConcurrencyLevel">Maximum concurrency level.</param>
/// <param name="useBackgroundThreads">True to set execution threads as background thread.</param>
public FixedThreadsTaskScheduler(int maxConcurrencyLevel, bool useBackgroundThreads = true)
public FixedThreadsTaskScheduler(string? name, int maxConcurrencyLevel, bool useBackgroundThreads = true)
{
if (maxConcurrencyLevel <= 0)
throw new ArgumentOutOfRangeException(nameof(maxConcurrencyLevel));
this.id = Interlocked.Increment(ref LatestId);
this.MaximumConcurrencyLevel = maxConcurrencyLevel;
this.Name = name;
this.useBackgroundThreads = useBackgroundThreads;
this.executionThreads = new List<Thread>(Math.Min(32, maxConcurrencyLevel));
}
Expand All @@ -65,7 +56,7 @@ public FixedThreadsTaskScheduler(int maxConcurrencyLevel, bool useBackgroundThre
/// <summary>
/// Get number of threads which are executing tasks.
/// </summary>
public int BusyThreadCount { get => this.numberOfBusyThreads; }
public int BusyThreadCount => this.numberOfBusyThreads;


/// <summary>
Expand All @@ -92,14 +83,12 @@ public void Dispose()
/// <summary>
/// Get number of active execution threads.
/// </summary>
public int ExecutionThreadCount { get => this.executionThreads.Count; }
public int ExecutionThreadCount => this.executionThreads.Count;


// Entry of execution thread.
void ExecutionThreadProc()
{
//var syncContext = new SyncContext(this);
//SynchronizationContext.SetSynchronizationContext(syncContext);
while (true)
{
// get next task
Expand All @@ -109,19 +98,16 @@ void ExecutionThreadProc()
return null;
if (this.scheduledTasks.IsNotEmpty())
{
return this.scheduledTasks.First.AsNonNull().Value.Also((_) =>
return this.scheduledTasks.First.AsNonNull().Value.Also(_ =>
{
this.scheduledTasks.RemoveFirst();
++this.numberOfBusyThreads;
});
}
else
{
Monitor.Wait(this.syncLock);
return null;
}
Monitor.Wait(this.syncLock);
return null;
});
if (task == null)
if (task is null)
{
if (this.isDisposed)
break;
Expand All @@ -131,14 +117,12 @@ void ExecutionThreadProc()
// execute task
try
{
//syncContext.OperationStarted();
this.TryExecuteTask(task);
}
finally
{
lock (this.syncLock)
--this.numberOfBusyThreads;
//syncContext.OperationCompleted();
}
}
lock (this.syncLock)
Expand All @@ -147,7 +131,7 @@ void ExecutionThreadProc()


/// <inheritdoc/>
protected override IEnumerable<Task>? GetScheduledTasks() => this.scheduledTasks;
protected override IEnumerable<Task> GetScheduledTasks() => this.scheduledTasks;


/// <summary>
Expand All @@ -161,6 +145,12 @@ public bool IsExecutionThread
return this.executionThreads.Contains(Thread.CurrentThread);
}
}


/// <summary>
/// Get name of scheduler.
/// </summary>
public string? Name { get; }


/// <inheritdoc/>
Expand All @@ -180,10 +170,10 @@ protected override void QueueTask(Task task)
Monitor.Pulse(this.syncLock);
else if (this.executionThreads.Count < this.MaximumConcurrencyLevel)
{
this.executionThreads.Add(new Thread(this.ExecutionThreadProc).Also((thread) =>
this.executionThreads.Add(new Thread(this.ExecutionThreadProc).Also(thread =>
{
thread.IsBackground = this.useBackgroundThreads;
thread.Name = $"FTTaskScheduler-{this.id}-{Interlocked.Increment(ref this.latestExecThreadId)}";
thread.Name = $"{this.Name ?? "FTTaskScheduler"} [{this.id}]-{Interlocked.Increment(ref this.latestExecThreadId)}";
thread.Start();
}));
}
Expand All @@ -199,7 +189,7 @@ protected override void QueueTask(Task task)
protected override bool TryDequeue(Task task) => this.syncLock.Lock(() =>
{
var node = this.scheduledTasks.First;
while (node != null)
while (node is not null)
{
if (node.Value == task)
{
Expand Down

0 comments on commit 2d1ebe1

Please sign in to comment.