//---------------------------------------------------------------------------- // Copyright (C) 2013-2015 Fabrice HARROUET (ENIB) // // Permission to use, copy, modify, distribute and sell this software // and its documentation for any purpose is hereby granted without fee, // provided that the above copyright notice appear in all copies and // that both that copyright notice and this permission notice appear // in supporting documentation. // The author makes no representations about the suitability of this // software for any purpose. // It is provided "as is" without express or implied warranty. //---------------------------------------------------------------------------- using System; using System.Threading; public class Fifo { protected volatile int[] _d; protected volatile int _r; protected volatile int _w; public Fifo(int capacity) { _d=new int[capacity]; _r=0; _w=0; } public void enqueue(int value) { _d[_w]=value; _w=(_w+1)%_d.Length; } public int // value dequeue() { int value=_d[_r]; _r=(_r+1)%_d.Length; return value; } public bool full() { return _r==(_w+1)%_d.Length; } public bool empty() { return _w==_r; } } public abstract class Worker { public static readonly object sync=new object(); public static Fifo fifo=new Fifo(10); public static volatile bool done=false; protected int _index; protected int _count; protected Thread _th; protected Worker(int index) { _index=index; _count=0; _th=new Thread(this._run); } public void start() { _th.Start(); } public void join() { _th.Join(); } public int Count { get { return _count; } } protected abstract void _run(); } public class Producer : Worker { public Producer(int index) : base(index) { } protected override void _run() { for(int i=0;i<1000;++i) { int value=_index+1; lock(sync) { while(fifo.full()) { Monitor.Wait(sync); } fifo.enqueue(value); Monitor.PulseAll(sync); } _count+=value; } } } public class Consumer : Worker { public Consumer(int index) : base(index) { } protected override void _run() { for(;;) { int value=-1; lock(sync) { while(!done&&fifo.empty()) { Monitor.Wait(sync); } if(done) { break; } value=fifo.dequeue(); Monitor.PulseAll(sync); } _count+=value; } } } public class Test { public static void Main(string[] args) { Producer[] p=new Producer[5]; Console.WriteLine("launching {0} producers",p.Length); for(int i=0;i