ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/experimental/server/Queue/Queue.java
Revision: 1.3
Committed: Tue Jan 2 01:50:17 2001 UTC (23 years, 4 months ago) by tdb
Branch: MAIN
Changes since 1.2: +71 -79 lines
Log Message:
Added support for the dynamic creation of queues upon request. Makes the
whole system more flexible, and hopefully will allow for the starting and stopping
of components within the system.

File Contents

# Content
1 //---PACKAGE DECLARATION---
2
3 //---IMPORTS---
4 import java.util.LinkedList;
5 import java.util.NoSuchElementException;
6 //import uk.ac.ukc.iscream.util.*;
7
8 /**
9 * A Queue class designed to operate in a multi-threaded environment, with
10 * added support for multiple "consumer" threads. Also offers blocking on
11 * the get() methods, which ensures the consumer waits until the queue
12 * actually contains some elements.
13 *
14 * @author $Author: tdb1 $
15 * @version $Id: Queue.java,v 1.2 2000/12/28 03:49:15 tdb1 Exp $
16 */
17 class Queue {
18
19 //---FINAL ATTRIBUTES---
20
21 /**
22 * The current CVS revision of this class
23 */
24 public static final String REVISION = "$Revision: 1.2 $";
25
26 //---STATIC METHODS---
27
28 //---CONSTRUCTORS---
29
30 //---PUBLIC METHODS---
31
32 /**
33 * This method adds a given object to every queue. It will notify
34 * any waiting consumers (on an empty queue) during this process.
35 *
36 * @param o An Object to be added to the queues.
37 */
38 public void add(Object o) {
39 for(int i=0; i < _lists.size(); i++) {
40 // skip over any gaps left in the list
41 if(_lists.get(i) != null) {
42 int s = ((LinkedList) _lists.get(i)).size();
43 synchronized(this) {
44 // add() does the same thing, but this ensures behaviour
45 ((LinkedList) _lists.get(i)).addLast(o);
46 }
47 // if the queue was empty before the add it is possible
48 // that a consumer is waiting... so we notify them
49 if (s == 0) {
50 synchronized(((LinkedList) _lists.get(i))) {
51 ((LinkedList) _lists.get(i)).notifyAll();
52 }
53 }
54 }
55 }
56 // we keep track of the total additions for the status() method
57 _count++;
58 }
59
60 /**
61 * This method returns an object from the front of a given queue.
62 * It will block until data exists in the queue if required.
63 *
64 * @return The object from the front of the queue.
65 * @throws InvalidQueueException if the queue does not exist.
66 */
67 public Object get(int queue) throws InvalidQueueException {
68 // make sure queue exists
69 if (queue >= _lists.size() || _lists.get(queue) == null) {
70 throw new InvalidQueueException("Requested queue "+queue+" does not exist");
71 }
72 // block if the queue is empty
73 if (((LinkedList) _lists.get(queue)).size() == 0) {
74 synchronized(((LinkedList) _lists.get(queue))) {
75 try { ((LinkedList) _lists.get(queue)).wait(); } catch(Exception e) {}
76 }
77 }
78 // get an item, it should never be null due to the blocking above
79 Object o = null;
80 synchronized(this) {
81 try {
82 o = ((LinkedList) _lists.get(queue)).removeFirst();
83 }
84 catch (NoSuchElementException e) {
85 // This should never happen !
86 }
87 }
88 return o;
89 }
90
91 /**
92 * This method returns a textual status of the queues. It
93 * is merely for observation, and would most likely be used
94 * by a larger "monitoring" component. Information returned
95 * includes the current size of each queue, and the total
96 * items passed through.
97 *
98 * @return A String message containing status information.
99 */
100 public String status() {
101 String status = "";
102 for(int i=0; i < _lists.size(); i++) {
103 // check for null entries
104 if(_lists.get(i) != null) {
105 status += "Queue number "+i+" contains "+((LinkedList) _lists.get(i)).size()+" elements";
106 status += "\n";
107 }
108 else {
109 status += "Slot number "+i+" is currently empty";
110 status += "\n";
111 }
112 }
113 status += "A total of "+_count+" elements have been added to the queues";
114 return status;
115 }
116
117 /**
118 * This method assigns a queue to a consumer. The idea behind
119 * this is to ensure that only 1 consumer can be associated with
120 * a given queue, otherwise the whole "blocking" thing fails
121 * miserably. Queues are created upon requested.
122 *
123 * It is IMPORTANT that removeQueue() is used when the queue is
124 * no longer required.
125 *
126 * @return An integer to be passed to the get() method.
127 */
128 public int getQueue() {
129 int pos = -1;
130 for(int i=0; i < _lists.size(); i++) {
131 if(_lists.get(i) == null) {
132 // found a gap, re-use it
133 pos = i;
134 _lists.set(i, new LinkedList());
135 }
136 }
137 if(pos == -1) {
138 //we didn't find a gap, add at end
139 pos = _lists.size();
140 _lists.add(pos, new LinkedList());
141 }
142 return pos;
143 }
144
145 /**
146 * This method sets a entry to null in the list. This ensures
147 * that it will no longer be added to after it is no longer
148 * required be a consumer.
149 *
150 * @param queue The integer identifier for the queue, given by getQueue().
151 */
152 public void removeQueue(int queue) {
153 _lists.set(queue, null);
154 }
155
156 /**
157 * Overrides the {@link java.lang.Object#toString() Object.toString()}
158 * method to provide clean logging (every class should have this).
159 *
160 * This uses the uk.ac.ukc.iscream.util.FormatName class
161 * to format the toString()
162 *
163 * @return the name of this class and its CVS revision
164 */
165 /*public String toString() {
166 return FormatName.getName(
167 _name,
168 getClass().getName(),
169 REVISION);
170 }*/
171
172 //---PRIVATE METHODS---
173
174 //---ACCESSOR/MUTATOR METHODS---
175
176 //---ATTRIBUTES---
177
178 /**
179 * The LinkedLists of queues.
180 */
181 private LinkedList _lists = new LinkedList();
182
183 /**
184 * A counter so we know how many data items have been
185 * passed through, for statistical purposes.
186 */
187 private int _count = 0;
188
189 /**
190 * This is the friendly identifier of the
191 * component this class is running in.
192 * eg, a Filter may be called "filter1",
193 * If this class does not have an owning
194 * component, a name from the configuration
195 * can be placed here. This name could also
196 * be changed to null for utility classes.
197 */
198 //private String _name = <!THIS SHOULD CALL A STATIC NAME IN THE COMPONENT CLASS FOR THIS OBJECT!>;
199
200 /**
201 * This holds a reference to the
202 * system logger that is being used.
203 */
204 //private Logger _logger = ReferenceManager.getInstance().getLogger();
205
206 //---STATIC ATTRIBUTES---
207
208 }