-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[MTGOSDK/Core] Add SyncThread parallelism
Allows for efficiently queuing and dispatching multiple concurrent requests to ensure I/O intensive callbacks do not stall the event loop.
- Loading branch information
Showing
8 changed files
with
242 additions
and
196 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/** @file | ||
Copyright (c) 2025, Cory Bennett. All rights reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
**/ | ||
|
||
using System.Collections.Generic; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
|
||
namespace MTGOSDK.Core; | ||
|
||
/// <summary> | ||
/// A task scheduler that ensures a limited degree of concurrency. | ||
/// </summary> | ||
public class ConcurrentTaskScheduler( | ||
int maxDegreeOfParallelism, | ||
CancellationToken cancellationToken) : TaskScheduler | ||
{ | ||
private readonly LinkedList<Task> _tasks = new(); | ||
private readonly SemaphoreSlim _semaphore = new(maxDegreeOfParallelism); | ||
|
||
protected override IEnumerable<Task> GetScheduledTasks() | ||
{ | ||
lock (_tasks) | ||
{ | ||
return _tasks.ToArray(); | ||
} | ||
} | ||
|
||
protected override void QueueTask(Task task) | ||
{ | ||
lock (_tasks) | ||
{ | ||
_tasks.AddLast(task); | ||
NotifyThreadPoolOfPendingWork(); | ||
} | ||
} | ||
|
||
private void NotifyThreadPoolOfPendingWork() | ||
{ | ||
// Skip propagating the CAS restrictions of the current thread to quickly | ||
// dispatch the work item to another thread in the thread pool. | ||
ThreadPool.UnsafeQueueUserWorkItem(async _ => | ||
{ | ||
try | ||
{ | ||
await _semaphore.WaitAsync(cancellationToken); | ||
|
||
while (true) | ||
{ | ||
Task item; | ||
lock (_tasks) | ||
{ | ||
if (_tasks.Count == 0) | ||
break; | ||
|
||
item = _tasks.First.Value; | ||
_tasks.RemoveFirst(); | ||
} | ||
base.TryExecuteTask(item); | ||
} | ||
} | ||
finally | ||
{ | ||
_semaphore.Release(); | ||
} | ||
}, null); | ||
} | ||
|
||
protected override bool TryExecuteTaskInline( | ||
Task task, | ||
bool taskWasPreviouslyQueued) | ||
{ | ||
if (taskWasPreviouslyQueued) | ||
{ | ||
if (TryDequeue(task)) | ||
{ | ||
return base.TryExecuteTask(task); | ||
} | ||
else | ||
{ | ||
return false; | ||
} | ||
} | ||
else | ||
{ | ||
return base.TryExecuteTask(task); | ||
} | ||
} | ||
|
||
protected override bool TryDequeue(Task task) | ||
{ | ||
lock (_tasks) | ||
{ | ||
return _tasks.Remove(task); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.