| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- namespace Invercargill.DataStructures {
- public class Fifo<T> : Enumerable<T>, Queue<T> {
-
- public bool is_unblocked { get { return !is_blocking; } }
-
- private bool is_blocking = true;
- private FifoItem<T>* first_item = null;
- private FifoItem<T>* last_item = null;
- public override int? peek_count() {
- return null;
- }
- public override EnumerableInfo get_info() {
- return new EnumerableInfo.infer_ultimate (this, EnumerableCategory.EXTERNAL);
- }
- public void unblock() {
- mutex.lock();
- is_blocking = false;
- cond.broadcast();
- mutex.unlock();
- }
- public void push(owned T item) {
- mutex.lock();
- FifoItem<T>* fifo_item = new FifoItem<T>() {
- item = item,
- };
- if(first_item == null) {
- first_item = fifo_item;
- last_item = fifo_item;
- }
- else {
- last_item->next_item = fifo_item;
- last_item = fifo_item;
- }
- cond.broadcast();
- mutex.unlock();
- }
- public void push_all(Enumerable<T> items) {
- mutex.lock();
- foreach (var item in items) {
- FifoItem<T>* fifo_item = new FifoItem<T>() {
- item = item,
- };
-
- if(first_item == null) {
- first_item = fifo_item;
- last_item = fifo_item;
- }
- else {
- last_item->next_item = fifo_item;
- last_item = fifo_item;
- }
- }
- cond.broadcast();
- mutex.unlock();
- }
- public T pop() throws SequenceError {
- mutex.lock();
- while(is_blocking && first_item == null){
- cond.wait(mutex);
- }
- var item = first_item;
- if(item != null) {
- first_item = item->next_item;
- }
- mutex.unlock();
- if(item == null) {
- throw new SequenceError.NO_ELEMENTS("No elements in unblocked queue to pop");
- }
- var result = item->item;
- delete item;
- return result;
- }
- public T peek() throws SequenceError {
- var item = first_item;
- if(item == null) {
- throw new SequenceError.NO_ELEMENTS("No elements in queue");
- }
- return item->item;
- }
- public void push_start(owned T item) {
- mutex.lock();
- FifoItem<T>* fifo_item = new FifoItem<T>() {
- next_item = first_item,
- item = item,
- };
- if(first_item == null) {
- last_item = fifo_item;
- }
- first_item = fifo_item;
- cond.broadcast();
- mutex.unlock();
- }
- private bool has_next() {
- mutex.lock();
- while(is_blocking && first_item == null){
- cond.wait(mutex);
- }
- var state = first_item != null;
- mutex.unlock();
- return state;
- }
- private T get_next() {
- mutex.lock();
- var item = first_item;
- first_item = item->next_item;
- mutex.unlock();
- var result = item->item;
- delete item;
- return result;
- }
- private Cond cond = Cond ();
- private Mutex mutex = Mutex ();
- public override Tracker<T> get_tracker () {
- return new LambdaTracker<T>(
- () => has_next(),
- () => get_next());
- }
- ~Fifo() {
- var n = first_item;
- while(n != null) {
- var c = n;
- n = n->next_item;
- delete c;
- }
- }
- [Compact]
- private class FifoItem<T> {
- public T item;
- public FifoItem<T>* next_item;
- }
- }
- }
|