'Dart equivalent of BlockingCollection

I'm currently migrating an App's logic code from C# to Dart and I'm looking for a similiar collection type in Dart to C#s BlockingCollection. I basically want a queue where i can iterate infinitely. If the queue is empty it just waits until a new element is added.

Is that possible in Dart?

Best



Solution 1:[1]

You can also write your own queue, based on futures instead of a stream:

import "dart:async" show Completer;
import "dart:collection" show Queue;

abstract class BlockingQueue<T> {
  factory BlockingQueue() = _BlockingQueue;
  Future<T> removeNext();
  void add(T value);
}

class _BlockingQueue<T> implements BlockingQueue<T> {
  final Queue<T> _writes = Queue();
  final Queue<Completer<T>> _reads = Queue();
  Future<T> removeNext() {
    if (_writes.isNotEmpty) return Future.value(_writes.removeFirst());
    var completer = Completer<T>();
    _reads.add(completer);
    return completer.future;
  }
  void add(T value) {
    if (_reads.isNotEmpty) {
      _reads.removeFirst().complete(value);
    } else {
      _writes.add(value);
    }
  }
}

You can also consider a double-blocking queue, where the add method also "blocks" if there is no-one to accept the value yet. It's not even that hard,.

import "dart:async" show Completer;
import "dart:collection" show Queue;

abstract class BlockingQueue<T> {
  factory BlockingQueue() = _BlockingQueue;
  Future<T> removeNext();
  Future<void> add(T value);
}

class _BlockingQueue<T> implements BlockingQueue<T> {
  final Queue<T> _writes = Queue();
  final Queue<Completer<T>> _completers = Queue();
  Future<T> removeNext() {

    if (_writes.isNotEmpty) {
      assert(_completers.isNotEmpty);
      var completer = _completers.removeFirst();
      completer.complete(_writes.removeFirst());
      return completer.future;
    }
    var completer = Completer<T>();
    _completers.add(completer);
    return completer.future;
  }
  Future<void> add(T value) {
    if (_writes.isEmpty && _completers.isNotEmpty) {
      var completer = _completers.removeFirst();
      completer.complete(value);
      return completer.future;
    }
    var completer = Completer<T>();
    _completers.add(completer);
    _writes.add(value);
    return completer.future;
  }
}

That said, if you want to use a for (... in ...)-like loop, you probably do want to go with a Stream and use await for (... in theStream).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 lrn