Let the user change the element-queue for AsyncQueue<T>#1606
Let the user change the element-queue for AsyncQueue<T>#1606TheConstructor wants to merge 1 commit into
Conversation
This allows the user to prioritize queued elements, or use an implementation otherwise different from Queue<T> as backend.
There was a problem hiding this comment.
Pull request overview
This PR extends AsyncQueue<T> to allow callers to supply a custom synchronous queue implementation for element storage, enabling alternative ordering/priority behaviors while reusing the existing async coordination logic.
Changes:
- Introduces a new public
ISyncQueue<T>interface for synchronous queue operations. - Adds an internal
SyncQueue<T>wrapper aroundQueue<T>as the default element store. - Adds an
AsyncQueue<T>constructor that accepts a queue factory, plus a test validating a custom element queue can be used.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| test/Microsoft.VisualStudio.Threading.Tests/AsyncQueueTests.cs | Adds coverage for using a custom element queue implementation; introduces a small test-only prioritized queue. |
| src/Microsoft.VisualStudio.Threading/SyncQueue`1.cs | Adds the default internal Queue<T>-backed implementation used when no factory is supplied. |
| src/Microsoft.VisualStudio.Threading/ISyncQueue`1.cs | Defines the new public abstraction that custom element queues must implement. |
| src/Microsoft.VisualStudio.Threading/AsyncQueue`1.cs | Switches element storage to ISyncQueue<T> and adds a constructor for supplying a custom factory. |
| /// <summary> | ||
| /// The factory for the internal queue of elements. A Queue`1 is constructed, when this is null. | ||
| /// </summary> | ||
| private readonly Func<int, ISyncQueue<T>>? elementsQueueFactory; |
| /// <param name="elementsQueueFactory">Factory to create the queue used for items, if needed. Takes the initial capacity.</param> | ||
| public AsyncQueue(Func<int, ISyncQueue<T>> elementsQueueFactory) | ||
| { | ||
| this.elementsQueueFactory = elementsQueueFactory; | ||
| } |
| /// <summary> | ||
| /// Adds an element to the tail of the queue. | ||
| /// </summary> | ||
| /// <param name="value">The value to add.</param> | ||
| void Enqueue(T value); |
| /// <summary> | ||
| /// Gets and removes the element at the head of the queue. | ||
| /// </summary> | ||
| /// <returns>The head element.</returns> | ||
| T Dequeue(); |
| /// <summary> | ||
| /// This "prioritied" queue implementation is not optimized for speed, nor does it allow custom types or ordering. | ||
| /// </summary> |
|
Thanks for your inclination toward sharing. The added abstraction around queue that you're adding appears to allow you to build a prioritized queue that you then plug into the system, but to this library, the abstraction adds no value without your plugin. As our OSS license is quite liberal, I suggest you copy the AsyncQueue code to make your own async prioritized queue for your needs. |
Would it be an option to make If you would rather accept a PR containing an AsyncPriorityQueue I could do that as well, but I thought having the abstraction would be a better fit |
|
TBH I don't know why we still have |
|
I have to admit, that I have no clue, why Which leaves |
|
@TheConstructor I filed #1617 to remove the obsolete class. |
This allows the user to prioritize queued elements, or use an implementation otherwise different from Queue as backend.
If you think an abstract class is a better fit than an interface or I should change anything else, just reach out (or do it).
I would be happy, if I could use the nice async-wrapper that is AsyncQueue around a queue, that prioritises items and keeps insertion-order between items of the same priority (which the channel from
Channel.CreateUnboundedPrioritized<T>()doesn't do). Now I don't think that this library needs to offer the whole thing, but AsyncQueue utilises some internal classes likeTaskCompletionSourceWithoutInlining<T>that I would need to replace, if I want to have a full-fledged copy, without a change in this repository