KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > util > event > EventMulticaster


1 /*
2  * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
3  * notice. All rights reserved.
4  */

5 package com.tc.util.event;
6
7 import java.io.Serializable JavaDoc;
8 import java.util.ArrayList JavaDoc;
9 import java.util.Collections JavaDoc;
10 import java.util.Iterator JavaDoc;
11 import java.util.LinkedList JavaDoc;
12 import java.util.List JavaDoc;
13
14 /**
15  * Generic Event/Listener implementation.
16  * <p>
17  * USAGE:
18  * </p>
19  *
20  * <pre>
21  * class Worker implements Runnable {
22  *
23  * private final EventMulticaster updateObserver;
24  *
25  * private void doWork() {
26  * if (stateChanged()) updateObserver.fireUpdateEvent();
27  *
28  * ...
29  *
30  * public void addWorkEventListener(UpdateEventListener listener) {
31  * updateObserver.addListener(listener);
32  *
33  * ...
34  *
35  * class Master {
36  *
37  * private void delegateTask() {
38  * Worker worker = new Worker();
39  * worker.addWorkEventListener(new UpdateEventListener() {
40  * public void handleUpdate(Object arg) {
41  * System.out.println(arg);
42  * }
43  * });
44  *
45  * ...
46  * </pre>
47  */

48 public final class EventMulticaster implements Serializable JavaDoc {
49
50   private transient UpdateEventListener eventListener;
51   private transient EventQueue queue;
52   private transient Thread JavaDoc dispatchThread;
53   private volatile boolean dispatchInterrupted;
54
55   public synchronized void enableDispatchThread() {
56     this.eventListener = null;
57     this.queue = new EventQueue();
58     this.dispatchThread = new Thread JavaDoc() {
59       public void run() {
60         UpdateEvent event = null;
61         try {
62           while (true) {
63             event = queue.take();
64             event.listener.handleUpdate(event.arg);
65           }
66         } catch (InterruptedException JavaDoc e) {
67           dispatchInterrupted = true;
68         }
69       }
70     };
71     dispatchThread.setDaemon(true);
72     dispatchThread.start();
73   }
74
75   public void fireUpdateEvent() {
76     fireUpdateEvent(null);
77   }
78
79   public synchronized void fireUpdateEvent(Object JavaDoc arg) {
80     if (dispatchInterrupted) throw new IllegalStateException JavaDoc();
81     if (eventListener != null) {
82       if (queue == null) eventListener.handleUpdate(arg);
83       else {
84         UpdateEvent event = new UpdateEvent();
85         event.listener = eventListener;
86         event.arg = arg;
87         queue.offer(event);
88       }
89     }
90   }
91
92   public synchronized void addListener(UpdateEventListener listener) {
93     if (eventListener == null) {
94       eventListener = listener;
95     } else if (eventListener instanceof EventMulticaster.BroadcastListener) {
96       EventMulticaster.BroadcastListener broadcast = (EventMulticaster.BroadcastListener) eventListener;
97       broadcast.add(listener);
98     } else {
99       EventMulticaster.BroadcastListener broadcast = new BroadcastListener();
100       broadcast.add(eventListener);
101       broadcast.add(listener);
102       eventListener = broadcast;
103     }
104   }
105
106   public synchronized boolean removeListener(UpdateEventListener listener) {
107     if (eventListener instanceof EventMulticaster.BroadcastListener) {
108       EventMulticaster.BroadcastListener broadcast = (EventMulticaster.BroadcastListener) eventListener;
109       if (!broadcast.remove(listener)) return false;
110       if (broadcast.size() == 1) eventListener = broadcast.pop();
111       return true;
112     } else {
113       if (eventListener != listener) return false;
114       eventListener = null;
115       return true;
116     }
117   }
118
119   // --------------------------------------------------------------------------------
120

121   private class BroadcastListener implements UpdateEventListener, Serializable JavaDoc {
122
123     private List JavaDoc listeners = Collections.synchronizedList(new ArrayList JavaDoc());
124
125     public void handleUpdate(Object JavaDoc arg) {
126       for (Iterator JavaDoc iter = listeners.iterator(); iter.hasNext();) {
127         if (queue == null) ((UpdateEventListener) iter.next()).handleUpdate(arg);
128         else {
129           UpdateEvent event = new UpdateEvent();
130           event.listener = (UpdateEventListener) iter.next();
131           event.arg = arg;
132           queue.offer(event);
133         }
134       }
135     }
136
137     private void add(UpdateEventListener listener) {
138       listeners.add(listener);
139     }
140
141     private boolean remove(UpdateEventListener listener) {
142       return listeners.remove(listener);
143     }
144
145     private int size() {
146       return listeners.size();
147     }
148
149     private UpdateEventListener pop() {
150       return (UpdateEventListener) listeners.iterator().next();
151     }
152   }
153
154   // --------------------------------------------------------------------------------
155

156   private class UpdateEvent implements Serializable JavaDoc {
157     private UpdateEventListener listener;
158     private Object JavaDoc arg;
159   }
160
161   // --------------------------------------------------------------------------------
162

163   private class EventQueue implements Serializable JavaDoc {
164
165     private final List JavaDoc list = new LinkedList JavaDoc();
166
167     private void offer(UpdateEvent val) {
168       if (val == null) throw new NullPointerException JavaDoc();
169       synchronized (list) {
170         list.add(val);
171         list.notify();
172       }
173     }
174
175     private UpdateEvent take() throws InterruptedException JavaDoc {
176       synchronized (list) {
177         while (list.size() == 0) {
178           list.wait();
179         }
180         return (UpdateEvent) list.remove(0);
181       }
182     }
183   }
184 }
185
Popular Tags