Source of CircularBuffer.java


  1: // Fig. 23.13: CircularBuffer.java
  2: // SynchronizedBuffer synchronizes access to a single shared integer.
  3: import java.util.concurrent.locks.Lock;
  4: import java.util.concurrent.locks.ReentrantLock;
  5: import java.util.concurrent.locks.Condition;
  6: 
  7: public class CircularBuffer implements Buffer
  8: {
  9:    // Lock to control synchronization with this buffer   
 10:    private Lock accessLock = new ReentrantLock();
 11: 
 12:    // conditions to control reading and writing
 13:    private Condition canWrite = accessLock.newCondition();
 14:    private Condition canRead = accessLock.newCondition();
 15: 
 16:    private int[] buffer = { -1, -1, -1 };
 17: 
 18:    private int occupiedBuffers = 0; // count number of buffers used
 19:    private int writeIndex = 0; // index to write next value
 20:    private int readIndex = 0; // index to read next value
 21:    
 22:    // place value into buffer
 23:    public void set( int value )
 24:    {
 25:       accessLock.lock(); // lock this object
 26:                
 27:       // output thread information and buffer information, then wait
 28:       try 
 29:       {
 30:          // while no empty locations, place thread in waiting state
 31:          while ( occupiedBuffers == buffer.length ) 
 32:          {
 33:             System.out.printf( "All buffers full. Producer waits.\n" );
 34:             canWrite.await();// await until a buffer element is free
 35:          } // end while
 36: 
 37:          buffer[ writeIndex ] = value; // set new buffer value
 38: 
 39:          // update circular write index
 40:          writeIndex = ( writeIndex + 1 ) % buffer.length;
 41: 
 42:          occupiedBuffers++; // one more buffer element is full
 43:          displayState( "Producer writes " + value );
 44:          canRead.signal(); // signal threads waiting to read from buffer
 45:       } // end try
 46:       catch ( InterruptedException exception )
 47:       {
 48:          exception.printStackTrace();
 49:       } // end catch
 50:       finally
 51:       {
 52:          accessLock.unlock(); // unlock this object
 53:       } // end finally
 54:    } // end method set
 55:     
 56:    // return value from buffer
 57:    public int get()
 58:    {
 59:       int readValue = 0; // initialize value read from buffer
 60:       accessLock.lock(); // lock this object
 61: 
 62:       // wait until buffer has data, then read value
 63:       try 
 64:       {
 65:          // while no data to read, place thread in waiting state
 66:          while ( occupiedBuffers == 0 ) 
 67:          {
 68:             System.out.printf( "All buffers empty. Consumer waits.\n" );
 69:             canRead.await(); // await until a buffer element is filled
 70:          } // end while
 71: 
 72:          readValue = buffer[ readIndex ]; // read value from buffer
 73: 
 74:          // update circular read index
 75:          readIndex = ( readIndex + 1 ) % buffer.length;
 76: 
 77:          occupiedBuffers--; // one more buffer element is empty
 78:          displayState( "Consumer reads " + readValue );
 79:          canWrite.signal(); // signal threads waiting to write to buffer
 80:       } // end try
 81:       // if waiting thread interrupted, print stack trace
 82:       catch ( InterruptedException exception ) 
 83:       {
 84:          exception.printStackTrace();
 85:       } // end catch
 86:       finally
 87:       {
 88:          accessLock.unlock(); // unlock this object
 89:       } // end finally
 90: 
 91:       return readValue;
 92:    } // end method get
 93:     
 94:    // display current operation and buffer state
 95:    public void displayState( String operation )
 96:    {
 97:       // output operation and number of occupied buffers
 98:       System.out.printf( "%s%s%d)\n%s", operation, 
 99:          " (buffers occupied: ", occupiedBuffers, "buffers:  " );
100: 
101:       for ( int value : buffer )
102:          System.out.printf( " %2d  ", value ); // output values in buffer
103: 
104:       System.out.print( "\n         " );
105:       for ( int i = 0; i < buffer.length; i++ )
106:          System.out.print( "---- " );
107: 
108:       System.out.print( "\n         " );
109:       for ( int i = 0; i < buffer.length; i++ )
110:       {
111:          if ( i == writeIndex && i == readIndex )
112:             System.out.print( " WR" ); // both write and read index
113:          else if ( i == writeIndex )
114:             System.out.print( " W   " ); // just write index
115:          else if ( i == readIndex )
116:             System.out.print( "  R  " ); // just read index
117:          else
118:             System.out.print( "     " ); // neither index
119:       } // end for
120: 
121:       System.out.println( "\n" );
122:    } // end method displayState
123: } // end class CircularBuffer
124: 
125: 
126: /**************************************************************************
127:  * (C) Copyright 1992-2005 by Deitel & Associates, Inc. and               *
128:  * Pearson Education, Inc. All Rights Reserved.                           *
129:  *                                                                        *
130:  * DISCLAIMER: The authors and publisher of this book have used their     *
131:  * best efforts in preparing the book. These efforts include the          *
132:  * development, research, and testing of the theories and programs        *
133:  * to determine their effectiveness. The authors and publisher make       *
134:  * no warranty of any kind, expressed or implied, with regard to these    *
135:  * programs or to the documentation contained in these books. The authors *
136:  * and publisher shall not be liable in any event for incidental or       *
137:  * consequential damages in connection with, or arising out of, the       *
138:  * furnishing, performance, or use of these programs.                     *
139:  *************************************************************************/