001: /*=============================================================================
002: * Copyright Texas Instruments 2002. All Rights Reserved.
003: *
004: * This program is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU General Public License as published by
006: * the Free Software Foundation; either version 2 of the License, or
007: * (at your option) any later version.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package ti.swing;
020:
021: import ti.pub.WorkerThread;
022:
023: import java.awt.*;
024: import java.util.LinkedList;
025:
026: /**
027: * A queue implementation with a {@link #enqueue} method and a blocking
028: * {@link #dequeue} method that is safe to call from the AWT event dispatch
029: * thread.
030: *
031: * @author Rob Clark
032: * @version 0.1
033: */
034: public class SwingQueue {
035: private Toolkit toolkit;
036: private LinkedList queue = new LinkedList();
037:
038: /**
039: * Class Constructor.
040: */
041: public SwingQueue() {
042: toolkit = Toolkit.getDefaultToolkit();
043: }
044:
045: /**
046: * Enqueue, potentially unblocking any threads that have called the
047: * {@link #dequeue} method.
048: *
049: * @param obj the object to enqueue
050: * @see #dequeue
051: */
052: public void enqueue(Object obj) {
053: synchronized (queue) {
054: queue.addFirst(obj);
055: queue.notify();
056:
057: /* in case dequeuing thread is blocked in getNextEvent(): (this depends
058: * a bit too much on the implementation of EventQueue... but what else
059: * can we do?)
060: */
061: EventQueue q = toolkit.getSystemEventQueue();
062: synchronized (q) {
063: q.notify();
064: }
065: }
066: }
067:
068: private int swingTimerCnt = 0;
069: private javax.swing.Timer swingTimer = new javax.swing.Timer(200,
070: new java.awt.event.ActionListener() {
071:
072: public void actionPerformed(
073: java.awt.event.ActionEvent evt) { /* no-op */
074: }
075:
076: });
077:
078: private synchronized void startTimer() {
079: if (swingTimerCnt == 0)
080: swingTimer.start();
081: swingTimerCnt++;
082: }
083:
084: private synchronized void stopTimer() {
085: swingTimerCnt--;
086: if (swingTimerCnt == 0)
087: swingTimer.stop();
088: }
089:
090: /**
091: * Dequeue item from queue, blocking until object is enqueued if the queue
092: * is currently empty. If multiple threads call this method it is not
093: * defined which one will dequeue an entry first. It is guaranteed that
094: * objects will be dequeued in the same order they are enqueued.
095: *
096: *
097: * @return the dequeued object
098: * @see #enqueue
099: */
100: public Object dequeue() {
101: while (true) {
102: synchronized (queue) {
103: if (queue.size() > 0)
104: return queue.removeLast();
105: }
106:
107: try {
108: if (javax.swing.SwingUtilities.isEventDispatchThread()) {
109: // there is a possibility for a race condition here, because we
110: // can't synchronize this w.r.t. enqueue() without blocking the
111: // enqueue() operation itself. It isn't too bad because presumably
112: // we will eventually get an event to dispatch, which will give us
113: // another chance to check to see if there is anything queued.
114: startTimer();
115: AWTEvent event = toolkit.getSystemEventQueue()
116: .getNextEvent();
117: stopTimer();
118: Object src = event.getSource();
119: // can't call theQueue.dispatchEvent, so I pasted its body here
120: if (event instanceof ActiveEvent)
121: ((ActiveEvent) event).dispatch();
122: else if (src instanceof Component)
123: ((Component) src).dispatchEvent(event);
124: else if (src instanceof MenuComponent)
125: ((MenuComponent) src).dispatchEvent(event);
126: else
127: System.err.println("unable to dispatch event: "
128: + event);
129: } else if (Thread.currentThread() instanceof WorkerThread) {
130: ((WorkerThread) (Thread.currentThread()))
131: .runNext(100);
132: } else {
133: synchronized (queue) {
134: if (queue.size() <= 0)
135: queue.wait();
136: }
137: }
138: } catch (InterruptedException e) {
139: Thread.interrupted();
140: }
141: }
142: }
143: }
144:
145: /*
146: * Local Variables:
147: * tab-width: 2
148: * indent-tabs-mode: nil
149: * mode: java
150: * c-indentation-style: java
151: * c-basic-offset: 2
152: * eval: (c-set-offset 'substatement-open '0)
153: * eval: (c-set-offset 'case-label '+)
154: * eval: (c-set-offset 'inclass '+)
155: * eval: (c-set-offset 'inline-open '0)
156: * End:
157: */
|