common: Annotate some Class.get*Name methods
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / internal / tmf / core / request / TmfRequestExecutor.java
CommitLineData
951d134a 1/*******************************************************************************
be4a197a 2 * Copyright (c) 2009, 2014 Ericsson
9b749023 3 *
951d134a
FC
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
9b749023 8 *
951d134a
FC
9 * Contributors:
10 * Francois Chouinard - Initial API and implementation
96b353c5 11 * Francois Chouinard - Added support for pre-emption
306586b1 12 * Simon Delisle - Added scheduler for requests
951d134a
FC
13 *******************************************************************************/
14
2bdf0193 15package org.eclipse.tracecompass.internal.tmf.core.request;
8c8bf09f 16
b30ff01f
MAL
17import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
18
96b353c5 19import java.util.Queue;
306586b1
SD
20import java.util.Timer;
21import java.util.TimerTask;
96b353c5 22import java.util.concurrent.ArrayBlockingQueue;
8c8bf09f 23import java.util.concurrent.Executor;
54d55ced 24import java.util.concurrent.ExecutorService;
8c8bf09f 25import java.util.concurrent.Executors;
9b635e61 26
2bdf0193
AM
27import org.eclipse.tracecompass.internal.tmf.core.TmfCoreTracer;
28import org.eclipse.tracecompass.internal.tmf.core.component.TmfEventThread;
29import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest.ExecutionType;
8c8bf09f 30
951d134a 31/**
306586b1
SD
32 * The request scheduler works with 5 slots with a specific time. It has 4 slots
33 * for foreground requests and 1 slot for background requests, and it passes
34 * through all the slots (foreground first and background after).
35 *
36 * Example: if we have one foreground and one background request, the foreground
37 * request will be executed four times more often than the background request.
9b749023 38 *
8fd82db5 39 * @author Francois Chouinard
306586b1 40 * @author Simon Delisle
96b353c5 41 * @version 1.1
951d134a 42 */
8c8bf09f
ASL
43public class TmfRequestExecutor implements Executor {
44
306586b1
SD
45 // ------------------------------------------------------------------------
46 // Constants
47 // ------------------------------------------------------------------------
48
49 private static final long REQUEST_TIME = 100;
50 private static final int FOREGROUND_SLOT = 4;
51
96b353c5
FC
52 // ------------------------------------------------------------------------
53 // Attributes
54 // ------------------------------------------------------------------------
55
56 // The request executor
306586b1 57 private final ExecutorService fExecutor = Executors.newCachedThreadPool();
11252342 58 private final String fExecutorName;
96b353c5 59
11252342 60 // The request queues
e1627b18
AM
61 private final Queue<TmfEventThread> fForegroundTasks = new ArrayBlockingQueue<>(10);
62 private final Queue<TmfEventThread> fBackgroundTasks = new ArrayBlockingQueue<>(10);
96b353c5 63
11252342
AM
64 // The tasks
65 private TmfEventThread fActiveTask;
306586b1 66
661b21a1 67 private Timer fTimer;
306586b1
SD
68 private TimerTask fTimerTask;
69
70 private int fForegroundCycle = 0;
fc6ccf6f 71
9b749023
AM
72 // ------------------------------------------------------------------------
73 // Constructors
74 // ------------------------------------------------------------------------
75
76 /**
77 * Default constructor
78 */
79 public TmfRequestExecutor() {
b30ff01f
MAL
80 // We know the canonical name is not null because we use ExecutorService only
81 String canonicalName = checkNotNull(fExecutor.getClass().getCanonicalName());
96b353c5
FC
82 fExecutorName = canonicalName.substring(canonicalName.lastIndexOf('.') + 1);
83 if (TmfCoreTracer.isComponentTraced()) {
84 TmfCoreTracer.trace(fExecutor + " created"); //$NON-NLS-1$
85 }
9b749023
AM
86 }
87
96b353c5
FC
88 // ------------------------------------------------------------------------
89 // Getters
90 // ------------------------------------------------------------------------
91
11252342
AM
92 /**
93 * @return the shutdown state (i.e. if it is accepting new requests)
94 */
e1627b18 95 public boolean isShutdown() {
11252342
AM
96 return fExecutor.isShutdown();
97 }
98
99 /**
100 * @return the termination state
101 */
e1627b18 102 public boolean isTerminated() {
11252342
AM
103 return fExecutor.isTerminated();
104 }
9b749023 105
96b353c5
FC
106 // ------------------------------------------------------------------------
107 // Operations
108 // ------------------------------------------------------------------------
9b749023 109
661b21a1
PT
110 /**
111 * Initialize the executor
112 */
113 public void init() {
114 if (fTimer != null) {
115 return;
116 }
117 // Initialize the timer for the schedSwitch
118 fTimerTask = new SchedSwitch();
119 fTimer = new Timer(true);
120 fTimer.schedule(fTimerTask, 0, REQUEST_TIME);
121 }
122
11252342
AM
123 @Override
124 public synchronized void execute(final Runnable command) {
96b353c5
FC
125
126 // We are expecting MyEventThread:s
127 if (!(command instanceof TmfEventThread)) {
128 // TODO: Log an error
129 return;
130 }
131
132 // Wrap the thread in a MyThread
133 TmfEventThread thread = (TmfEventThread) command;
134 TmfEventThread wrapper = new TmfEventThread(thread) {
475743b7 135 @Override
96b353c5
FC
136 public void run() {
137 try {
138 command.run();
139 } finally {
140 scheduleNext();
141 }
475743b7 142 }
96b353c5
FC
143 };
144
145 // Add the thread to the appropriate queue
5419a136 146 ExecutionType priority = thread.getExecType();
96b353c5 147
306586b1 148 if (priority == ExecutionType.FOREGROUND) {
e1627b18
AM
149 if (!fForegroundTasks.offer(wrapper)) {
150 wrapper.cancel();
151 }
306586b1 152 } else {
e1627b18
AM
153 if (!fBackgroundTasks.offer(wrapper)) {
154 wrapper.cancel();
155 }
306586b1
SD
156 }
157 }
158
159 /**
160 * Timer task to trigger scheduleNext()
161 */
162 private class SchedSwitch extends TimerTask {
163
164 SchedSwitch() {
165 }
166
167 @Override
168 public void run() {
96b353c5
FC
169 scheduleNext();
170 }
11252342
AM
171 }
172
173 /**
174 * Executes the next pending request, if applicable.
175 */
176 protected synchronized void scheduleNext() {
177 if (!isShutdown()) {
306586b1
SD
178 if (fActiveTask == null) {
179 schedule();
180 } else if (fActiveTask.getExecType() == ExecutionType.FOREGROUND) {
181 if (fActiveTask.getThread().isCompleted()) {
6dcda2b7 182 fActiveTask = null;
306586b1
SD
183 schedule();
184 } else {
185 if (hasTasks()) {
186 fActiveTask.getThread().suspend();
e1627b18
AM
187 if (!fForegroundTasks.offer(fActiveTask)) {
188 fActiveTask.cancel();
189 fActiveTask = null;
190 }
306586b1
SD
191 schedule();
192 }
193 }
194
195 } else if (fActiveTask.getExecType() == ExecutionType.BACKGROUND) {
196 if (fActiveTask.getThread().isCompleted()) {
6dcda2b7 197 fActiveTask = null;
306586b1
SD
198 schedule();
199 } else {
200 if (hasTasks()) {
201 fActiveTask.getThread().suspend();
e1627b18
AM
202 if (!fBackgroundTasks.offer(fActiveTask)) {
203 fActiveTask.cancel();
204 fActiveTask = null;
205 }
306586b1
SD
206 schedule();
207 }
208 }
11252342
AM
209 }
210 }
211 }
8c8bf09f 212
96b353c5
FC
213 /**
214 * Stops the executor
215 */
216 public synchronized void stop() {
661b21a1
PT
217 if (fTimerTask != null) {
218 fTimerTask.cancel();
219 }
220
221 if (fTimer != null) {
222 fTimer.cancel();
223 }
b67f3f7c 224
96b353c5
FC
225 if (fActiveTask != null) {
226 fActiveTask.cancel();
227 }
228
306586b1
SD
229 while ((fActiveTask = fForegroundTasks.poll()) != null) {
230 fActiveTask.cancel();
231 }
232 while ((fActiveTask = fBackgroundTasks.poll()) != null) {
96b353c5
FC
233 fActiveTask.cancel();
234 }
235
236 fExecutor.shutdown();
237 if (TmfCoreTracer.isComponentTraced()) {
238 TmfCoreTracer.trace(fExecutor + " terminated"); //$NON-NLS-1$
239 }
240 }
241
306586b1
SD
242 // ------------------------------------------------------------------------
243 // Helper methods
244 // ------------------------------------------------------------------------
245
246 /**
247 * Determine which type of request (foreground or background) we schedule
248 * next
249 */
250 private void schedule() {
251 if (!fForegroundTasks.isEmpty()) {
252 scheduleNextForeground();
253 } else {
254 scheduleNextBackground();
255 }
256 }
257
258 /**
259 * Schedule the next foreground request
260 */
261 private void scheduleNextForeground() {
262 if (fForegroundCycle < FOREGROUND_SLOT || fBackgroundTasks.isEmpty()) {
263 ++fForegroundCycle;
264 fActiveTask = fForegroundTasks.poll();
265 executefActiveTask();
266 } else {
267 fActiveTask = null;
268 scheduleNextBackground();
269 }
270 }
271
272 /**
273 * Schedule the next background request
274 */
275 private void scheduleNextBackground() {
276 fForegroundCycle = 0;
277 if (!fBackgroundTasks.isEmpty()) {
278 fActiveTask = fBackgroundTasks.poll();
279 executefActiveTask();
280 }
281 }
282
283 /**
284 * Execute or resume the active task
285 */
286 private void executefActiveTask() {
287 if (fActiveTask.getThread().isPaused()) {
288 fActiveTask.getThread().resume();
289 } else {
290 fExecutor.execute(fActiveTask);
291 }
292 }
293
294 /**
295 * Check if the scheduler has tasks
296 */
297 private boolean hasTasks() {
298 return !(fForegroundTasks.isEmpty() && fBackgroundTasks.isEmpty());
299 }
300
11252342
AM
301 // ------------------------------------------------------------------------
302 // Object
303 // ------------------------------------------------------------------------
5c00c0b7 304
11252342 305 @Override
3b38ea61 306 @SuppressWarnings("nls")
11252342
AM
307 public String toString() {
308 return "[TmfRequestExecutor(" + fExecutorName + ")]";
309 }
8c8bf09f
ASL
310
311}
This page took 0.120722 seconds and 5 git commands to generate.