/* * DataChannel.java Copyright (c) 1996 Chuck McManis, all rights reserved. * * Copyright (c) 1996 Chuck McManis, All Rights Reserved. * * Permission to use, copy, modify, and distribute this software * and its documentation for NON-COMMERCIAL purposes and without * fee is hereby granted provided that this copyright notice * appears in all copies. * * CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS * SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT * OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. */ package util.comm; import java.util.Hashtable; import java.util.Enumeration; /** * The DataChannel class is the base class of the inter-thread based * communication system. */ public class DataChannel { /** * This is the registry of all Data Channels that are * currently open. */ private static Hashtable registry = null; /** * Each data channel has a hash table of threads that * are consuming events for this channel. */ private Hashtable TIDs; /** * This is the string identifier for this data channel */ String myName; /** * create a new named data channel. */ private DataChannel() { TIDs = new Hashtable(); } /** * Return a data channel from the registry with the given name. * If it doesn't exist it is created. This item is suitable * for a PRODUCER to use. To get an channel that a CONSUMER * can use, call getItem with non-zero queue size. */ public static synchronized DataChannel getChannel(String name) { if (registry == null) registry = new Hashtable(); DataChannel it = (DataChannel) registry.get(name); if (it == null) { it = new DataChannel(); it.myName = name; registry.put(name, it); } return it; } /** * Return a data channel to a CONSUMER with the given name. * If it doesn't exist it is created. The named data channel * is updated to include a queue for this thread. */ public static DataChannel getChannel(String name, Thread myTID, int qSize) { DataChannel it = getChannel(name); if (qSize == 0) return it; it.TIDs.put(myTID, new DataItem(myTID, qSize)); return it; } /** * Write a value into this data channel. All consumer * threads will be notified of the availability of new * data. If there are no consumer threads this is * essentially a NOP. */ public synchronized void putValue(Object x) { for (Enumeration e = TIDs.elements(); e.hasMoreElements(); ) { ((DataItem)(e.nextElement())).insert(x); } } /** * Return the value in this Data Channel. If there isn't any * data in the channel this call blocks. */ public Object getValue() throws DataChannelOverrun, DataChannelTimeout, DataChannelShutdown { DataItem di = (DataItem) TIDs.get(Thread.currentThread()); return ((di != null) ? di.fetch() : null); } /** return true if the Data channel has data waiting to be read. */ public boolean hasData() { DataItem di = (DataItem) TIDs.get(Thread.currentThread()); return ((di != null) ? di.hasData() : false); } public Object lastValue() { DataItem di = (DataItem) TIDs.get(Thread.currentThread()); return (di != null) ? (di.lastValue()) : null; } public void shutDown() { for (Enumeration e = TIDs.elements(); e.hasMoreElements(); ) { ((DataItem)(e.nextElement())).delete(); } } public synchronized void releaseChannel(Thread tid) { DataItem x = (DataItem) TIDs.remove(tid); if (x != null) { x.delete(); } } }