Mega Code Archive

 
Categories / C# / Thread
 

Producer and consumer with a Circular Buffer

/* Code revised from Book published by  (C) Copyright 1992-2006 by Deitel & Associates, Inc. and Pearson Education, Inc. All Rights Reserved.   */ using System; using System.Threading; public class Producer  {    private CircularBuffer sharedLocation;    private Random randomSleepTime;    public Producer( CircularBuffer shared, Random random )    {       sharedLocation = shared;       randomSleepTime = random;    }    public void Produce()    {       for ( int count = 1; count <= 10; count++ )        {          Thread.Sleep( randomSleepTime.Next( 1, 3001 ) );          sharedLocation.Buffer = count;        }        Console.WriteLine( "{0} done producing.\nTerminating {0}.", Thread.CurrentThread.Name );    } } public class Consumer {    private CircularBuffer sharedLocation;    private Random randomSleepTime;    public Consumer( CircularBuffer shared, Random random )    {       sharedLocation = shared;       randomSleepTime = random;    }    public void Consume()    {       int sum = 0;       for ( int count = 1; count <= 10; count++ )       {          Thread.Sleep( randomSleepTime.Next( 1, 3001 ) );          sum += sharedLocation.Buffer;       }       Console.WriteLine("{0} read values totaling: {1}.\nTerminating {0}.",          Thread.CurrentThread.Name, sum );    } } public class CircularBuffer {    private int[] buffers = { -1, -1, -1 };    private int occupiedBufferCount = 0;    private int readLocation = 0;     private int writeLocation = 0;        public int Buffer    {       get       {          lock ( this )          {             if ( occupiedBufferCount == 0 )             {                Console.Write( "\nAll buffers empty. {0} waits.",Thread.CurrentThread.Name );                Monitor.Wait( this );             }              int readValue = buffers[ readLocation ];             Console.Write( "\n{0} reads {1} ",Thread.CurrentThread.Name, buffers[ readLocation ] );             --occupiedBufferCount;             readLocation = ( readLocation + 1 ) % buffers.Length;             Console.Write( CreateStateOutput() );             Monitor.Pulse( this );             return readValue;          }       }       set       {          lock ( this )          {             if ( occupiedBufferCount == buffers.Length )             {                Console.Write( "\nAll buffers full. {0} waits.",Thread.CurrentThread.Name );                Monitor.Wait( this );             }             buffers[ writeLocation ] = value;             Console.Write( "\n{0} writes {1} ",Thread.CurrentThread.Name, buffers[ writeLocation ] );             ++occupiedBufferCount;             writeLocation = ( writeLocation + 1 ) % buffers.Length;             Console.Write( CreateStateOutput() );             Monitor.Pulse( this );          }       }    }    public string CreateStateOutput()    {       string output = "(buffers occupied: " + occupiedBufferCount + ")\nbuffers: ";       for ( int i = 0; i < buffers.Length; i++ )          output += " " + string.Format( "{0,2}", buffers[ i ] ) + "  ";       output += "\n";       output += "         ";       for ( int i = 0; i < buffers.Length; i++ )          output += "---- ";       output += "\n";       output += "         ";       for ( int i = 0; i < buffers.Length; i++ )        {          if ( i == writeLocation &&              writeLocation == readLocation )              output += " WR  ";          else if ( i == writeLocation )             output += " W   ";          else if  ( i == readLocation )              output += "  R  ";          else             output += "     ";       }       output += "\n";       return output;    }    static void Main( string[] args )    {       CircularBuffer shared = new CircularBuffer();       Random random = new Random();       Console.Write( shared.CreateStateOutput() );       Producer producer = new Producer( shared, random );       Consumer consumer = new Consumer( shared, random );       Thread producerThread = new Thread( new ThreadStart( producer.Produce ) );       producerThread.Name = "Producer";       Thread consumerThread = new Thread( new ThreadStart( consumer.Consume ) );       consumerThread.Name = "Consumer";       producerThread.Start();       consumerThread.Start();    }     }