4using System.Threading.Tasks;
17 private readonly LinkedList<Item> queue =
new LinkedList<Item>();
18 private readonly LinkedList<TaskCompletionSource<T>> subscribers =
new LinkedList<TaskCompletionSource<T>>();
19 private readonly TaskCompletionSource<bool> terminatedTask =
new TaskCompletionSource<bool>();
20 private readonly
object synchObj =
new object();
21 private volatile int countItems = 0;
22 private volatile int countSubscribers = 0;
23 private bool disposed =
false;
24 private bool terminated =
false;
25 private bool empty =
true;
26 private bool waiting =
false;
38 internal T Value {
get; }
39 internal TaskCompletionSource<bool> Forwarded;
41 internal Item(T Value)
44 this.Forwarded =
null;
47 internal Item(T Value, TaskCompletionSource<bool> Forwarded)
50 this.Forwarded = Forwarded;
63 return this.countItems;
77 return this.countSubscribers;
115 [Obsolete(
"Use the Forward or Queue methods instead, for increased clarity.")]
116 public Task<bool>
Add(T Item)
118 return this.
Forward(Item,
false);
126 [Obsolete(
"Use the Forward or Queue methods instead, for increased clarity.")]
129 return this.
Forward(Item,
false);
137 [Obsolete(
"Use the Forward or Queue methods instead, for increased clarity.")]
140 return this.
Forward(Item,
true);
149 [Obsolete(
"Use the Forward or Queue methods instead, for increased clarity.")]
150 public Task<bool>
Add(T Item,
bool First)
152 return this.
Forward(Item, First);
162 this.
Queue(Item,
false);
172 this.
Queue(Item,
false);
182 this.
Queue(Item,
true);
191 public void Queue(T Item,
bool First)
193 EventHandler h =
null;
197 if (this.terminated || this.disposed)
200 if (this.subscribers.First is
null)
202 Item Record =
new Item(Item);
205 this.queue.AddFirst(Record);
207 this.queue.AddLast(Record);
218 TaskCompletionSource<T> Waiter = this.subscribers.First.Value;
219 this.subscribers.RemoveFirst();
220 this.countSubscribers--;
221 if (this.countSubscribers <= 0)
223 this.waiting =
false;
227 Task.Run(() => Waiter.TrySetResult(Item));
231 h?.Raise(
this, EventArgs.Empty);
241 return this.
Forward(Item,
false);
251 return this.
Forward(Item,
false);
261 return this.
Forward(Item,
true);
272 EventHandler h =
null;
277 if (this.terminated || this.disposed)
278 return Task.FromResult(
false);
280 if (this.subscribers.First is
null)
282 TaskCompletionSource<bool> Forwarded =
new TaskCompletionSource<bool>();
284 Item Record =
new Item(Item, Forwarded);
287 this.queue.AddFirst(Record);
289 this.queue.AddLast(Record);
298 Result = Record.Forwarded.Task;
302 TaskCompletionSource<T> Waiter = this.subscribers.First.Value;
303 this.subscribers.RemoveFirst();
304 this.countSubscribers--;
305 if (this.countSubscribers <= 0)
307 this.waiting =
false;
311 Waiter.TrySetResult(Item);
313 Result = Task.FromResult(
true);
317 h?.Raise(
this, EventArgs.Empty);
329 return this.DoWait(CancellationToken.None,
null);
339 public Task<T>
Wait(
int Timeout)
341 return this.DoWait(CancellationToken.None, Timeout);
351 public Task<T>
Wait(CancellationToken Cancel)
353 return this.DoWait(Cancel,
null);
364 public Task<T>
Wait(CancellationToken Cancel,
int Timeout)
366 return this.DoWait(Cancel, Timeout);
377 private Task<T> DoWait(CancellationToken Cancel,
int? Timeout)
379 EventHandler h =
null;
383 if (Timeout.HasValue && Timeout.Value <= 0)
384 throw new ArgumentException(
"Timeout must be positive.", nameof(Timeout));
388 if (this.queue.First is
null)
391 return Task.FromResult<T>(
null);
393 TaskCompletionSource<T> Item =
new TaskCompletionSource<T>();
395 if (Cancel.CanBeCanceled)
397 Cancel.Register(() => Item.TrySetResult(
null));
398 if (Cancel.IsCancellationRequested)
399 return Task.FromResult<T>(
null);
402 this.subscribers.AddLast(Item);
403 this.countSubscribers++;
412 if (Timeout.HasValue)
414 Task.Delay(Timeout.Value).ContinueWith((
_) =>
416 EventHandler h2 =
null;
420 if (!this.disposed && this.subscribers.Remove(Item))
422 this.countSubscribers--;
423 if (this.countSubscribers <= 0)
425 this.waiting =
false;
429 Item.TrySetResult(
null);
433 h2?.Raise(
this, EventArgs.Empty);
435 return Task.CompletedTask;
441 Record = this.queue.First.Value;
442 this.queue.RemoveFirst();
444 if (this.countItems <= 0)
450 Record.Forwarded?.TrySetResult(
true);
452 if (this.terminated && this.queue.First is
null)
454 this.disposed =
true;
455 this.terminatedTask.TrySetResult(
true);
458 Result = Task.FromResult(Record.Value);
462 h?.Raise(
this, EventArgs.Empty);
489 private bool TryGetItem(
bool Remove, out T Item)
491 EventHandler h =
null;
496 if (this.disposed || this.queue.First is
null)
503 Item Record = this.queue.First.Value;
508 this.queue.RemoveFirst();
510 if (this.countItems <= 0)
516 Record.Forwarded?.TrySetResult(
true);
518 if (this.terminated && this.queue.First is
null)
520 this.disposed =
true;
531 h?.Raise(
this, EventArgs.Empty);
546 this.disposed =
true;
547 this.terminated =
true;
549 foreach (Item Record
in this.queue)
550 Record.Forwarded?.TrySetResult(
false);
555 foreach (TaskCompletionSource<T> Task
in this.subscribers)
556 Task.TrySetResult(
null);
558 this.subscribers.Clear();
559 this.countSubscribers = 0;
562 this.RaiseDisposed();
574 this.terminated =
true;
576 if (this.queue.First is
null)
578 this.disposed =
true;
580 foreach (Item Record
in this.queue)
581 Record.Forwarded?.TrySetResult(
false);
586 foreach (TaskCompletionSource<T> Task
in this.subscribers)
587 Task.TrySetResult(
null);
589 this.subscribers.Clear();
590 this.countSubscribers = 0;
593 return this.terminatedTask.Task;
596 this.RaiseDisposed();
597 return this.terminatedTask.Task;
625 private void RaiseDisposed()
629 this.terminatedTask.TrySetResult(
true);
631 this.Disposed.Raise(
this, EventArgs.Empty);
Static class managing the application event log. Applications and services log events on this static ...
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Asynchronous First-in-First-out (FIFO) Queue, for use when transporting items of type T between task...
Task Terminate()
Terminates the queue, allowing subscribers to get queued items, but disallows new items to be added....
Task< bool > AddFirst(T Item)
Adds an item first to the queue.
Task< bool > Forward(T Item, bool First)
Processes an item by adding it to the queue.
Task< bool > Forward(T Item)
Processes an item by adding it last in the queue.
Task< bool > ForwardLast(T Item)
Processes an item by adding it last in the queue.
void QueueLast(T Item)
Queues an item for processing by adding it last in the queue. No information is returned wether the i...
EventHandler OnNotEmpty
Event raised when Empty changed to false.
EventHandler OnWaiting
Event raised when Waiting changed to true.
EventHandler OnEmpty
Event raised when Empty changed to true.
Task< T > Wait()
Waits indefinitely (or until queue is disposed) for an item to be available. If Queue is disposed,...
bool Waiting
If there are subscribers waiting for work.
int CountSubscribers
Number of subscribers waiting for items.
void Queue(T Item)
Queues an item for processing by adding it last in the queue. No information is returned wether the i...
void QueueFirst(T Item)
Queues an item for processing by adding it first in the queue. No information is returned wether the ...
void Queue(T Item, bool First)
Queues an item for processing. No information is returned wether the item is forwarded for processing...
Task< bool > ForwardFirst(T Item)
Processes an item by adding it first in the queue.
bool TryGetItem(out T Item)
Tries to get a queued item, if found. If not, the method returns immediately with a null item.
Task< T > Wait(int Timeout)
Waits indefinitely (or until queue is disposed) for an item to be available. If Queue is disposed,...
bool Empty
If the queue is empty.
void Dispose()
IDisposable.Dispose
EventHandler Disposed
Event raised when queue has been disposed.
EventHandler OnNotWaiting
Event raised when Waiting changed to false.
Task< bool > AddLast(T Item)
Adds an item last to the queue.
AsyncQueue()
Asynchronous Queue, for use when transporting items of class T between tasks.
Task< T > Wait(CancellationToken Cancel, int Timeout)
Waits indefinitely (or until queue is disposed or task cancelled) for an item to be available....
Task< bool > Add(T Item)
Adds an item last to the queue.
Task< bool > Add(T Item, bool First)
Adds an item to the queue.
int CountItems
Number of items in queue.
bool TryPeekItem(out T Item)
Tries to get a queued item, if found. If not, the method returns immediately with a null item.
Task< T > Wait(CancellationToken Cancel)
Waits indefinitely (or until queue is disposed or task cancelled) for an item to be available....