// // $Source: /home/cur/djb1/java/threads/RCS/Channel.java,v $ // // $Id: Channel.java,v 1.1 1996/10/02 15:19:50 djb1 Exp $ // // Channel class - an occam CHAN for multiple readers and writers. // // (C) Copyright 1996 Peter Welch
* There is no logical buffering of data in the channel. The object passed * into the channel is not cloned, but rather a reference is passed to the * reader. Therefore, care must be taken that the object supplied by a writer * does not then have its content modified asynchronously by the writer. This * can be done by setting the reference to null, e.g. in a writer,
* * String s = "Hello World"; // create a new string * chan.write(s); // send the string * s = null; // delete writer's reference to string * ** or alternatively, a clone can be supplied, e.g.
* * StringBuffer s = "Hello World"; // create a new string * chan.write(s.clone()); // send the string * s.reverse(); // does not affect the reader's copy ** *@version $Revision: 1.1 $ *@author Peter Welch, P.H.Welch@ukc.ac.uk *@author Dave Beckett, D.J.Beckett@ukc.ac.uk *@author with annotations by Richard Beton */ //}}} class Channel { //{{{ private member data private Object channel_hold; // buffer (not detectable to users) private boolean channel_empty = true; // synchronisation flag private Object read_monitor = // all readers multiplex through this new Object (); private Object write_monitor = // all writers multiplex through this new Object (); //}}} //{{{ read method /** * read method: read a message from the channel. This method * blocks until a corresponding thread calls the write method, * at which point a rendezvous is formed and the data is passed. * *@return the object sent from the writing thread. * *@exception InterruptedException * Occurs if the wait methods are interrupted. */ public Object read () throws InterruptedException { synchronized (read_monitor) { synchronized (this) { if (channel_empty) { channel_empty = false; // first to the rendezvous wait (); // wait for the writer thread notify (); // schedule the writer to finish } else { channel_empty = true; // second to the rendezvous notify (); // schedule the waiting writer thread } return channel_hold; } } } //}}} //{{{ write method /** * write method: write a message to the channel. This method * blocks until a corresponding thread calls the read method, * at which point a rendezvous is formed and the data is passed. * *@param o the object to be sent to the reading thread. * *@exception InterruptedException * Occurs if the wait methods are interrupted. */ public void write (Object o) throws InterruptedException { synchronized (write_monitor) { synchronized (this) { channel_hold = o; if (channel_empty) { channel_empty = false; // first to the rendezvous wait (); // wait for the reader thread } else { channel_empty = true; // second to the rendezvous notify (); // schedule the waiting reader thread wait (); // let the reader regain this monitor } } } } //}}} //{{{ is_empty method /** * is_empty method: determine whether a thread is waiting at the * other end of the channel. This can be used either at the writing or the * reading end of the channel. * *@return true iff no thread is waiting at the other end. */ public boolean is_empty () { return channel_empty; } //}}} }