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