1 package org.apache.commons.jcs.engine.control.event;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.IOException;
23 import java.util.concurrent.LinkedBlockingQueue;
24 import java.util.concurrent.ThreadPoolExecutor;
25 import java.util.concurrent.TimeUnit;
26
27 import org.apache.commons.jcs.engine.control.event.behavior.IElementEvent;
28 import org.apache.commons.jcs.engine.control.event.behavior.IElementEventHandler;
29 import org.apache.commons.jcs.engine.control.event.behavior.IElementEventQueue;
30 import org.apache.commons.jcs.utils.threadpool.DaemonThreadFactory;
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33
34
35
36
37 public class ElementEventQueue
38 implements IElementEventQueue
39 {
40 private static final String THREAD_PREFIX = "JCS-ElementEventQueue-";
41
42
43 private static final Log log = LogFactory.getLog( ElementEventQueue.class );
44
45
46 private boolean destroyed = false;
47
48
49 private LinkedBlockingQueue<Runnable> queue;
50
51
52 private ThreadPoolExecutor queueProcessor;
53
54
55
56
57 public ElementEventQueue()
58 {
59 queue = new LinkedBlockingQueue<Runnable>();
60 queueProcessor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
61 queue, new DaemonThreadFactory(THREAD_PREFIX));
62
63 if ( log.isDebugEnabled() )
64 {
65 log.debug( "Constructed: " + this );
66 }
67 }
68
69
70
71
72 @Override
73 public void dispose()
74 {
75 if ( !destroyed )
76 {
77 destroyed = true;
78
79
80
81 queueProcessor.shutdownNow();
82 queueProcessor = null;
83
84 if ( log.isInfoEnabled() )
85 {
86 log.info( "Element event queue destroyed: " + this );
87 }
88 }
89 }
90
91
92
93
94
95
96
97 @Override
98 public <T> void addElementEvent( IElementEventHandler hand, IElementEvent<T> event )
99 throws IOException
100 {
101
102 if ( log.isDebugEnabled() )
103 {
104 log.debug( "Adding Event Handler to QUEUE, !destroyed = " + !destroyed );
105 }
106
107 if (destroyed)
108 {
109 log.warn("Event submitted to disposed element event queue " + event);
110 }
111 else
112 {
113 ElementEventRunner runner = new ElementEventRunner( hand, event );
114
115 if ( log.isDebugEnabled() )
116 {
117 log.debug( "runner = " + runner );
118 }
119
120 queueProcessor.execute(runner);
121 }
122 }
123
124
125
126
127
128
129 protected abstract class AbstractElementEventRunner
130 implements Runnable
131 {
132
133
134
135 @SuppressWarnings("synthetic-access")
136 @Override
137 public void run()
138 {
139 try
140 {
141 doRun();
142
143 }
144 catch ( IOException e )
145 {
146
147 log.warn( "Giving up element event handling " + ElementEventQueue.this, e );
148 }
149 }
150
151
152
153
154
155
156 protected abstract void doRun()
157 throws IOException;
158 }
159
160
161
162
163 private class ElementEventRunner
164 extends AbstractElementEventRunner
165 {
166
167 private final IElementEventHandler hand;
168
169
170 private final IElementEvent<?> event;
171
172
173
174
175
176
177
178
179 @SuppressWarnings("synthetic-access")
180 ElementEventRunner( IElementEventHandler hand, IElementEvent<?> event )
181 throws IOException
182 {
183 if ( log.isDebugEnabled() )
184 {
185 log.debug( "Constructing " + this );
186 }
187 this.hand = hand;
188 this.event = event;
189 }
190
191
192
193
194
195
196 @Override
197 protected void doRun()
198 throws IOException
199 {
200 hand.handleElementEvent( event );
201 }
202 }
203 }