All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.randelshofer.quaqua.util.EventLoop Maven / Gradle / Ivy

Go to download

A Mavenisation of the Quaqua Mac OSX Swing Look and Feel (Java library) Quaqua Look and Feel (C) 2003-2010, Werner Randelshofer. Mavenisation by Matt Gumbley, DevZendo.org - for problems with Mavenisation, see Matt; for issues with Quaqua, see the Quaqua home page. For full license details, see http://randelshofer.ch/quaqua/license.html

The newest version!
/*
 * @(#)EventLoop.java  1.4  2009-06-01
 *
 * Copyright (c) 2001-2010 Werner Randelshofer, Immensee, Switzerland.
 * All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with Werner Randelshofer.
 * For details see accompanying license terms.
 */
//package ch.randelshofer.util;
package ch.randelshofer.quaqua.util;

import java.util.*;
/**
 * An EventLoop can process events on a separate worker thread.
 * It consists of two parts: the event collector and the event
 * processor.
 * 

* The event collector collects all incoming events and puts them * into a queue.
* The event processor removes the events from the queue and * processes them. *

* The key feature of the EventLoop is, that clients don't have * to wait until an event has been processed. Clients are free * to proceed as soon as the collector has put the event into * the queue. *

* Other important features are that events are processed in * the same sequence as they have been collected and that only one * thread is used to process the events. *

* Usage *

* This is an abstract class. It does all the queue handling, but * does no processing. To use it, you have to create a subclass * which overrides the methods #collectEvent and #processEvent. *

* Example *

* An EventLoop, which outputs Strings on a background thread * could look like this: *


 * public class AsyncDisplay
 * extends AbstractEventLoop {
 *     public void display(String string) {
 *         collectEvent(string);
 *     }
 *     protected void processEvent(Object event) {
 *          System.out.println((String) event);
 *    }
 * }
 * 
*

* To use the class proceed like this: *


 * AsyncDisplay a = new AsyncDisplay();
 *  a.display("Hello World");
 * 
* * @author Werner Randelshofer * @version 1.4 2009-06-01 Added method dispose. *
1.3 2006-04-07 Fixed bug in processEvents method. Support for * FIFO sequence added. Replaced Vector by LinkedList. *
1.2AWT 2001-09-24 Support for coalescing of events added. *
1.1 2001-08-24 Reworked for JDK 1.3. *
1.0.2 2000-03-03 * Catch SecurityException's (To make this class work in Netscape Navigator). *
history 1.0.1 14.10.1998 * Versionskennung in Klassenkommentar eingef�gt. *
history 1.0 Datum ? * Threads werden nicht mehr wiederverwendet. */ public abstract class EventLoop { private Thread eventProcessor; private int threadPriority; private final LinkedList eventQueue = new LinkedList(); /** * Indicates whether multiple events will be coalesced * by the event processor or not. */ private boolean isCoalesce; /** * Indicates whether events will be processed by the * event processor or not. */ private volatile boolean isAlive = true; /** * Indicates whether events shall be enqueued add the beginning * of the queue. */ private volatile boolean isLIFO = false; /** * Creates a new EventLoop which processes events at Thread.NORM_PRORITY. */ public EventLoop() { this(Thread.NORM_PRIORITY); } /** * Creates a new EventLoop which processes events at the * desired thread priority. * * @param priority The Thread priority of the event processor. */ public EventLoop(int priority) { this.threadPriority = priority; } /** * Collects an event and puts it into the event queue * for later processing. * * @param event The event to be put into the queue. */ protected void collectEvent(Object event) { synchronized(eventQueue) { if (! isCoalesce || ! eventQueue.contains(event)) { if (isLIFO) { eventQueue.addFirst(event); } else { eventQueue.addLast(event); } if (isAlive) startProcessor(); } } } /** * Sets whether the EventLoop coalesces multiple pending events. * A busy application may not be able to keep up with event * generation, causing multiple events to be queued. * Coalescing is based on equality tests of event objects. * More formally, coalesces an event o if and only if the queue * contains at least one element e such that * (o==null ? e==null : o.equals(e)). *

* EventLoops do not coalesce events by default. * * @param b Specify true to turn on coalescing. */ public void setCoalesce(boolean b) { isCoalesce = b; } /** * Returns true if the EventLoop * coalesces multiple pending events. * * @see #setCoalesce(boolean) */ public boolean isCoalesce() { return isCoalesce; } /** * Sets whether the EventLoop shall enqueue events at the beginning of the * queue instead of at the end of the queue. * * @param b Specify true to enqueue events at the beginning of the queue. */ public void setLIFO(boolean b) { isLIFO = b; } /** * Returns true if the EventLoop * coalesces multiple pending events. * * @see #setCoalesce(boolean) */ public boolean isLIFO() { return isLIFO; } /** * Starts the event processor. *
The event processor is started by default. */ public void start() { synchronized(eventQueue) { isAlive = true; startProcessor(); } } /** * Stops the event processor. */ public void stop() { isAlive = false; } /** * Clears the event queue. */ public void clear() { synchronized(eventQueue) { eventQueue.clear(); } } public void dispose() { stop(); clear(); } /** * This is the method which really starts the processor. */ private void startProcessor() { synchronized(eventQueue) { if (eventProcessor == null) { eventProcessor = new Thread(this+" Event Processor") { public void run() { processEvents(); } }; try { // The event processor must not be a daemon. // If it was a daemon, the virtual machine would // stop before the event had been processed. eventProcessor.setDaemon(false); } catch (SecurityException e) {} try { eventProcessor.setPriority(threadPriority); } catch (SecurityException e) {} eventProcessor.start(); } } } /** * This method processes an event on the event processor thread. * * @param event An event from the queue. */ protected abstract void processEvent(Object event); /** * This method removes events from the event queue * and proceses them until the queue is empty or * until #stop is called. *

* This method must be called from the event processor * thread only. */ protected void processEvents() { Object event; while (true) { synchronized(eventQueue) { if (eventQueue.isEmpty() || ! isAlive) { eventProcessor = null; return; } event = eventQueue.removeFirst(); } try { processEvent(event); } catch (Throwable e) { e.printStackTrace(); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy