KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > framework > eventmgr > ListenerQueue


1 /*******************************************************************************
2  * Copyright (c) 2003, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.osgi.framework.eventmgr;
13
14 import java.util.ArrayList JavaDoc;
15 import org.eclipse.osgi.framework.eventmgr.EventListeners.ListElement;
16 import org.eclipse.osgi.framework.eventmgr.EventManager.EventThread;
17
18 /**
19  * The ListenerQueue is used to snapshot the set of listeners at the time the event
20  * is fired. The snapshot list is then used to dispatch
21  * events to those listeners. A ListenerQueue object is associated with a
22  * specific EventManager object. ListenerQueue objects constructed with the same
23  * EventManager object will get in-order delivery of events
24  * using asynchronous delivery. No delivery order is guaranteed for synchronous
25  * delivery to avoid any potential deadly embraces.
26  *
27  * <p>ListenerQueue objects are created as necesssary to build a set of listeners
28  * that should receive a specific event or events. Once the set is created, the event
29  * can then be synchronously or asynchronously delivered to the set of
30  * listeners. After the event has been dispatched for delivery, the
31  * ListenerQueue object should be discarded as it is likely the list of listeners is stale.
32  * A new ListenerQueue object should be created when it is time to deliver
33  * another event. The memory cost of a ListenerQueue object is
34  * low since the ListenerQueue object shares the array of listeners with the EventListeners
35  * object which are queued.
36  * EventListeners uses copy-on-write semantics for managing the array and will copy the array
37  * before changing it once the array has been shared with a ListenerQueue. This minimizes
38  * object creation while guaranteeing the snapshot list is never modified once created.
39  * @since 3.1
40  */

41 public class ListenerQueue {
42     /**
43      * EventManager with which this queue is associated.
44      */

45     protected final EventManager manager;
46     /**
47      * A list of listener lists.
48      */

49     private final ArrayList JavaDoc queue;
50
51     /**
52      * Once the listener queue has been used to dispatch an event,
53      * you cannot add modify the queue.
54      * Access to this field must be protected by a synchronized region.
55      */

56     private boolean readOnly;
57
58     /**
59      * ListenerQueue constructor. This method creates an empty snapshop list.
60      *
61      * @param manager The EventManager this queue is associated with.
62      * @throws IllegalArgumentException If manager is null.
63      */

64     public ListenerQueue(EventManager manager) {
65         if (manager == null) {
66             throw new IllegalArgumentException JavaDoc();
67         }
68
69         this.manager = manager;
70         queue = new ArrayList JavaDoc();
71         readOnly = false;
72     }
73
74     /**
75      * Add a listener list to the snapshot list. This method can be called multiple times, prior to
76      * calling one of the dispatchEvent methods, to build the set of listeners for the
77      * delivery of a specific event. The current list of listeners in the specified EventListeners
78      * object is added to the snapshot list.
79      *
80      * @param listeners An EventListeners object to add to the queue. The current listeners
81      * in the EventListeners object will be called when an event is dispatched.
82      * @param dispatcher An EventDispatcher object to use when dispatching an event
83      * to the listeners on the specified EventListeners.
84      * @throws IllegalStateException If called after one of the dispatch methods has been called.
85      */

86     public synchronized void queueListeners(EventListeners listeners, EventDispatcher dispatcher) {
87         if (readOnly) {
88             throw new IllegalStateException JavaDoc();
89         }
90
91         if (listeners != null) {
92             ListElement[] list = listeners.getListeners();
93
94             if (list.length > 0) {
95                 queue.add(new EventListeners.ListElement(list, dispatcher));
96             }
97         }
98     }
99
100     /**
101      * Asynchronously dispatch an event to the snapshot list. An event dispatch thread
102      * maintained by the associated EventManager is used to deliver the events.
103      * This method may return immediately to the caller.
104      *
105      * @param eventAction This value is passed to the EventDispatcher.
106      * @param eventObject This object is passed to the EventDispatcher.
107      */

108     public void dispatchEventAsynchronous(int eventAction, Object JavaDoc eventObject) {
109         synchronized (this) {
110             readOnly = true;
111         }
112         EventThread eventThread = manager.getEventThread();
113         synchronized (eventThread) { /* synchronize on the EventThread to ensure no interleaving of posting to the event thread */
114             int size = queue.size();
115             for (int i = 0; i < size; i++) { /* iterate over the list of listener lists */
116                 ListElement list = (ListElement)queue.get(i);
117                 eventThread.postEvent((ListElement[]) list.primary, (EventDispatcher) list.companion, eventAction, eventObject);
118             }
119         }
120     }
121
122     /**
123      * Synchronously dispatch an event to the snapshot list. The event may
124      * be dispatched on the current thread or an event dispatch thread
125      * maintained by the associated EventManager.
126      * This method will not return to the caller until the EventDispatcher
127      * has been called (and has returned) for each listener on the queue.
128      *
129      * @param eventAction This value is passed to the EventDispatcher.
130      * @param eventObject This object is passed to the EventDispatcher.
131      */

132     public void dispatchEventSynchronous(int eventAction, Object JavaDoc eventObject) {
133         synchronized (this) {
134             readOnly = true;
135         }
136         // We can't guarantee any delivery order for synchronous events.
137
// Attempts to do so result in deadly embraces.
138
int size = queue.size();
139         for (int i = 0; i < size; i++) { /* iterate over the list of listener lists */
140             ListElement list = (ListElement)queue.get(i);
141             EventManager.dispatchEvent((ListElement[]) list.primary, (EventDispatcher) list.companion, eventAction, eventObject);
142         }
143     }
144 }
145
Popular Tags