/* * `gnu.iou' * Copyright (C) 2006 John Pritchard. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA */ package gnu.iou ; /** * Pipe for <tt>`bbo'</tt> and <tt>`bbi'</tt> implements input * blocking over <tt>`bbuf'</tt>. * * <p><b>Usage</b> * * <pre> * bbp pipe = new bbp(); * OutputStream pipeOut = new bbo(pipe); * InputStream pipeIn = new bbi(pipe); * </pre> * * <p><b>Thread safety</b> * * <p> This class is multi- thread safe only in the standard I/O API * defined here and used by <bb>`bbo'</bb> and <tt>`bbi'</tt>. * <i>Note that `bbuf' is not multi- thread safe.</i> * * <p> The mutex locker is accessable via the <tt>`getLocker()'</tt> * method. * * @author John Pritchard (john@syntelos.org) * * @see bbo * @see bbi * @see dbo */ public class bbp extends bbuf { protected final lck locker = new lck(); protected boolean apierrors = true; public bbp(){ super(); } /** * @param api_exc If true, throw exceptions on I/O methods that * shouldn't be used on the pipe. */ public bbp( boolean api_exc){ super(); this.apierrors = api_exc; } public bbp ( int init){ super(init); } public bbp ( byte[] buffer){ super(buffer); } // bbp public lck getLocker(){ return locker;} // InputStream public synchronized int read() { while (true){ if ( 0 < super.available()){ try { locker.serialize(null); if ( 0 < super.available()) return super.read(); } finally { locker.unlock(null); } } try { synchronized(this){ this.wait(); continue; } } catch ( InterruptedException intx){ return -1; } } } public synchronized int read(byte b[]) { return this.read( b, 0, b.length); } public synchronized int read(byte b[], int off, int len) { while (true){ if ( 0 < super.available()){ try { locker.serialize(null); if ( 0 < super.available()) return super.read(b, off, len); } finally { locker.unlock(null); } } try { synchronized(this){ this.wait(); continue; } } catch ( InterruptedException intx){ return -1; } } } public long skip(long n) { if (apierrors) throw new IllegalStateException("Skip not available on pipe."); else return 0L; } public void mark(int readlimit) {} public void reset() { if (apierrors) throw new IllegalStateException("Reset not available on pipe."); } public boolean markSupported() { return false; } // OutputStream public synchronized void write(int b) { try { locker.serialize(null); super.write(b); synchronized(this){ this.notifyAll(); } } finally { locker.unlock(null); } } public synchronized int write(byte b[]) { try { locker.serialize(null); int rc = super.write( b, 0, b.length); synchronized(this){ this.notifyAll(); } return rc; } finally { locker.unlock(null); } } public synchronized int write(byte b[], int off, int len) { try { locker.serialize(null); int rc = super.write( b, off, len); synchronized(this){ this.notifyAll(); } return rc; } finally { locker.unlock(null); } } public void flush() { if (apierrors) throw new IllegalStateException("Flush not available on pipe."); } public void close() { if (apierrors) throw new IllegalStateException("Close not available on pipe, will be GC'ed."); } }