ss: Move plugins to Trace Compass namespace
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / 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
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;
fd3f1eff 27import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest.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
e1627b18
AM
59 private final Queue<TmfEventThread> fForegroundTasks = new ArrayBlockingQueue<>(10);
60 private final Queue<TmfEventThread> fBackgroundTasks = new ArrayBlockingQueue<>(10);
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
96b353c5
FC
85 // ------------------------------------------------------------------------
86 // Getters
87 // ------------------------------------------------------------------------
88
11252342
AM
89 /**
90 * @return the shutdown state (i.e. if it is accepting new requests)
91 */
e1627b18 92 public boolean isShutdown() {
11252342
AM
93 return fExecutor.isShutdown();
94 }
95
96 /**
97 * @return the termination state
98 */
e1627b18 99 public boolean isTerminated() {
11252342
AM
100 return fExecutor.isTerminated();
101 }
9b749023 102
96b353c5
FC
103 // ------------------------------------------------------------------------
104 // Operations
105 // ------------------------------------------------------------------------
9b749023 106
661b21a1
PT
107 /**
108 * Initialize the executor
109 */
110 public void init() {
111 if (fTimer != null) {
112 return;
113 }
114 // Initialize the timer for the schedSwitch
115 fTimerTask = new SchedSwitch();
116 fTimer = new Timer(true);
117 fTimer.schedule(fTimerTask, 0, REQUEST_TIME);
118 }
119
11252342
AM
120 @Override
121 public synchronized void execute(final Runnable command) {
96b353c5
FC
122
123 // We are expecting MyEventThread:s
124 if (!(command instanceof TmfEventThread)) {
125 // TODO: Log an error
126 return;
127 }
128
129 // Wrap the thread in a MyThread
130 TmfEventThread thread = (TmfEventThread) command;
131 TmfEventThread wrapper = new TmfEventThread(thread) {
475743b7 132 @Override
96b353c5
FC
133 public void run() {
134 try {
135 command.run();
136 } finally {
137 scheduleNext();
138 }
475743b7 139 }
96b353c5
FC
140 };
141
142 // Add the thread to the appropriate queue
5419a136 143 ExecutionType priority = thread.getExecType();
96b353c5 144
306586b1 145 if (priority == ExecutionType.FOREGROUND) {
e1627b18
AM
146 if (!fForegroundTasks.offer(wrapper)) {
147 wrapper.cancel();
148 }
306586b1 149 } else {
e1627b18
AM
150 if (!fBackgroundTasks.offer(wrapper)) {
151 wrapper.cancel();
152 }
306586b1
SD
153 }
154 }
155
156 /**
157 * Timer task to trigger scheduleNext()
158 */
159 private class SchedSwitch extends TimerTask {
160
161 SchedSwitch() {
162 }
163
164 @Override
165 public void run() {
96b353c5
FC
166 scheduleNext();
167 }
11252342
AM
168 }
169
170 /**
171 * Executes the next pending request, if applicable.
172 */
173 protected synchronized void scheduleNext() {
174 if (!isShutdown()) {
306586b1
SD
175 if (fActiveTask == null) {
176 schedule();
177 } else if (fActiveTask.getExecType() == ExecutionType.FOREGROUND) {
178 if (fActiveTask.getThread().isCompleted()) {
6dcda2b7 179 fActiveTask = null;
306586b1
SD
180 schedule();
181 } else {
182 if (hasTasks()) {
183 fActiveTask.getThread().suspend();
e1627b18
AM
184 if (!fForegroundTasks.offer(fActiveTask)) {
185 fActiveTask.cancel();
186 fActiveTask = null;
187 }
306586b1
SD
188 schedule();
189 }
190 }
191
192 } else if (fActiveTask.getExecType() == ExecutionType.BACKGROUND) {
193 if (fActiveTask.getThread().isCompleted()) {
6dcda2b7 194 fActiveTask = null;
306586b1
SD
195 schedule();
196 } else {
197 if (hasTasks()) {
198 fActiveTask.getThread().suspend();
e1627b18
AM
199 if (!fBackgroundTasks.offer(fActiveTask)) {
200 fActiveTask.cancel();
201 fActiveTask = null;
202 }
306586b1
SD
203 schedule();
204 }
205 }
11252342
AM
206 }
207 }
208 }
8c8bf09f 209
96b353c5
FC
210 /**
211 * Stops the executor
212 */
213 public synchronized void stop() {
661b21a1
PT
214 if (fTimerTask != null) {
215 fTimerTask.cancel();
216 }
217
218 if (fTimer != null) {
219 fTimer.cancel();
220 }
b67f3f7c 221
96b353c5
FC
222 if (fActiveTask != null) {
223 fActiveTask.cancel();
224 }
225
306586b1
SD
226 while ((fActiveTask = fForegroundTasks.poll()) != null) {
227 fActiveTask.cancel();
228 }
229 while ((fActiveTask = fBackgroundTasks.poll()) != null) {
96b353c5
FC
230 fActiveTask.cancel();
231 }
232
233 fExecutor.shutdown();
234 if (TmfCoreTracer.isComponentTraced()) {
235 TmfCoreTracer.trace(fExecutor + " terminated"); //$NON-NLS-1$
236 }
237 }
238
306586b1
SD
239 // ------------------------------------------------------------------------
240 // Helper methods
241 // ------------------------------------------------------------------------
242
243 /**
244 * Determine which type of request (foreground or background) we schedule
245 * next
246 */
247 private void schedule() {
248 if (!fForegroundTasks.isEmpty()) {
249 scheduleNextForeground();
250 } else {
251 scheduleNextBackground();
252 }
253 }
254
255 /**
256 * Schedule the next foreground request
257 */
258 private void scheduleNextForeground() {
259 if (fForegroundCycle < FOREGROUND_SLOT || fBackgroundTasks.isEmpty()) {
260 ++fForegroundCycle;
261 fActiveTask = fForegroundTasks.poll();
262 executefActiveTask();
263 } else {
264 fActiveTask = null;
265 scheduleNextBackground();
266 }
267 }
268
269 /**
270 * Schedule the next background request
271 */
272 private void scheduleNextBackground() {
273 fForegroundCycle = 0;
274 if (!fBackgroundTasks.isEmpty()) {
275 fActiveTask = fBackgroundTasks.poll();
276 executefActiveTask();
277 }
278 }
279
280 /**
281 * Execute or resume the active task
282 */
283 private void executefActiveTask() {
284 if (fActiveTask.getThread().isPaused()) {
285 fActiveTask.getThread().resume();
286 } else {
287 fExecutor.execute(fActiveTask);
288 }
289 }
290
291 /**
292 * Check if the scheduler has tasks
293 */
294 private boolean hasTasks() {
295 return !(fForegroundTasks.isEmpty() && fBackgroundTasks.isEmpty());
296 }
297
11252342
AM
298 // ------------------------------------------------------------------------
299 // Object
300 // ------------------------------------------------------------------------
5c00c0b7 301
11252342 302 @Override
3b38ea61 303 @SuppressWarnings("nls")
11252342
AM
304 public String toString() {
305 return "[TmfRequestExecutor(" + fExecutorName + ")]";
306 }
8c8bf09f
ASL
307
308}
This page took 0.153576 seconds and 5 git commands to generate.