/*=============================================================================
* Copyright Texas Instruments 2002. All Rights Reserved.
*
* 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 ti.swing;
import ti.pub.WorkerThread;
import java.awt.*;
import java.util.LinkedList;
/**
* A queue implementation with a {@link #enqueue} method and a blocking
* {@link #dequeue} method that is safe to call from the AWT event dispatch
* thread.
*
* @author Rob Clark
* @version 0.1
*/
public class SwingQueue
{
private Toolkit toolkit;
private LinkedList queue = new LinkedList();
/**
* Class Constructor.
*/
public SwingQueue()
{
toolkit = Toolkit.getDefaultToolkit();
}
/**
* Enqueue, potentially unblocking any threads that have called the
* {@link #dequeue} method.
*
* @param obj the object to enqueue
* @see #dequeue
*/
public void enqueue( Object obj )
{
synchronized(queue)
{
queue.addFirst(obj);
queue.notify();
/* in case dequeuing thread is blocked in getNextEvent(): (this depends
* a bit too much on the implementation of EventQueue... but what else
* can we do?)
*/
EventQueue q = toolkit.getSystemEventQueue();
synchronized(q)
{
q.notify();
}
}
}
private int swingTimerCnt = 0;
private javax.swing.Timer swingTimer =
new javax.swing.Timer( 200, new java.awt.event.ActionListener() {
public void actionPerformed( java.awt.event.ActionEvent evt ) { /* no-op */ }
} );
private synchronized void startTimer()
{
if( swingTimerCnt == 0 )
swingTimer.start();
swingTimerCnt++;
}
private synchronized void stopTimer()
{
swingTimerCnt--;
if( swingTimerCnt == 0 )
swingTimer.stop();
}
/**
* Dequeue item from queue, blocking until object is enqueued if the queue
* is currently empty. If multiple threads call this method it is not
* defined which one will dequeue an entry first. It is guaranteed that
* objects will be dequeued in the same order they are enqueued.
*
*
* @return the dequeued object
* @see #enqueue
*/
public Object dequeue()
{
while(true)
{
synchronized(queue)
{
if( queue.size() > 0 )
return queue.removeLast();
}
try
{
if( javax.swing.SwingUtilities.isEventDispatchThread() )
{
// there is a possibility for a race condition here, because we
// can't synchronize this w.r.t. enqueue() without blocking the
// enqueue() operation itself. It isn't too bad because presumably
// we will eventually get an event to dispatch, which will give us
// another chance to check to see if there is anything queued.
startTimer();
AWTEvent event = toolkit.getSystemEventQueue().getNextEvent();
stopTimer();
Object src = event.getSource();
// can't call theQueue.dispatchEvent, so I pasted its body here
if( event instanceof ActiveEvent )
((ActiveEvent)event).dispatch();
else if( src instanceof Component )
((Component)src).dispatchEvent(event);
else if( src instanceof MenuComponent )
((MenuComponent)src).dispatchEvent(event);
else
System.err.println("unable to dispatch event: " + event);
}
else if( Thread.currentThread() instanceof WorkerThread )
{
((WorkerThread)(Thread.currentThread())).runNext(100);
}
else
{
synchronized(queue)
{
if( queue.size() <= 0 )
queue.wait();
}
}
}
catch(InterruptedException e)
{
Thread.interrupted();
}
}
}
}
/*
* Local Variables:
* tab-width: 2
* indent-tabs-mode: nil
* mode: java
* c-indentation-style: java
* c-basic-offset: 2
* eval: (c-set-offset 'substatement-open '0)
* eval: (c-set-offset 'case-label '+)
* eval: (c-set-offset 'inclass '+)
* eval: (c-set-offset 'inline-open '0)
* End:
*/
|