final class · System.Threading

BlockingCollection<T>

public final class BlockingCollection<T>

A queue that hands items from producers to consumers: Take waits for an item; after CompleteAdding, Take on an empty queue throws and TryTake gives false.

Kind
final class
Namespace
System.Threading
Assembly
System.Core
Access
public, final
Source file
Threading.ant

Type parameters

NameConstraints
Tany type

Inheritance

Base classes
Any BlockingCollection<T>

Constructors

new()
#

Properties

bool IsAddingCompleted { get; }
#

read-only

bool IsCompleted { get; }
#

read-only

i32 Count { get; }
#

read-only

Methods

Add(T item)
#
Take() : T
#

The next item (waiting for one).

WaitForItem() : bool
#

Whether an item can be taken (waiting for one, unless adding is complete); then Take gives it at once to this consumer only if no other one takes it first.

CompleteAdding()
#
Dispose()
#

Frees what it holds (it must not be used after).

Private and internal members (5)

Mutex mutex
#

private

Condition changed
#

private

Queue<T> items
#

private

bool completed
#

private

i32 waiters
#

private

Inherited members (5)

Source

BlockingCollection<T> as Antril, decompiled from its Larva HIR.

System.Threading.BlockingCollection.ant
// System.Threading.BlockingCollection — System.Core (decompiled from Larva HIR)

import System;

into namespace System.Threading
{
	/// A queue that hands items from producers to consumers: Take waits for an item; after CompleteAdding, Take on an
	/// empty queue throws and TryTake gives false.
	public final class BlockingCollection<T>
	{
		Mutex mutex;
		Condition changed;
		Queue<T> items;
		bool completed;
		i32 waiters;

		public:
			new()
			{
				mutex = new Mutex();
				changed = new Condition();
				items = new Queue<T>();
			}

			Add(T item)
			{
				mutex.Lock();
				if (completed)
				{
					mutex.Unlock();
					throw new InvalidOperationError("BlockingCollection: adding is complete");
				}
				items.Enqueue(item);
				bool wake = waiters > 0;
				mutex.Unlock();
				if (wake)
					changed.Signal();
			}

			/// The next item (waiting for one).
			Take() : T
			{
				mutex.Lock();
				loop (items.Count == 0)
				{
					if (completed)
					{
						mutex.Unlock();
						throw new InvalidOperationError("BlockingCollection: empty and adding is complete");
					}
					waiters++;
					changed.Wait(mutex);
					waiters--;
				}
				T item = items.Dequeue();
				mutex.Unlock();
				return item;
			}

			/// Whether an item can be taken (waiting for one, unless adding is complete); then Take gives it at once to
			/// this consumer only if no other one takes it first.
			WaitForItem() : bool
			{
				mutex.Lock();
				loop (items.Count == 0 && !completed)
				{
					waiters++;
					changed.Wait(mutex);
					waiters--;
				}
				bool any = items.Count > 0;
				mutex.Unlock();
				return any;
			}

			CompleteAdding()
			{
				mutex.Lock();
				completed = true;
				mutex.Unlock();
				changed.Broadcast();
			}

			/// Frees what it holds (it must not be used after).
			Dispose()
			{
				mutex.Dispose();
				changed.Dispose();
			}

			bool IsAddingCompleted
			{
				get => completed;
			}

			bool IsCompleted
			{
				get
				{
					mutex.Lock();
					bool done = completed && items.Count == 0;
					mutex.Unlock();
					return done;
				}
			}

			i32 Count
			{
				get => items.Count;
			}
	}
}
Esc