tmf: Support tool tip for arrows in time graph
[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
a4524c1b
AM
59 private final Queue<TmfEventThread> fForegroundTasks = new ArrayBlockingQueue<>(100);
60 private final Queue<TmfEventThread> fBackgroundTasks = new ArrayBlockingQueue<>(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
96b353c5
FC
85 // ------------------------------------------------------------------------
86 // Getters
87 // ------------------------------------------------------------------------
88
11252342
AM
89 /**
90 * @return the shutdown state (i.e. if it is accepting new requests)
91 */
92 public synchronized boolean isShutdown() {
93 return fExecutor.isShutdown();
94 }
95
96 /**
97 * @return the termination state
98 */
99 public synchronized boolean isTerminated() {
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
SD
145 if (priority == ExecutionType.FOREGROUND) {
146 fForegroundTasks.add(wrapper);
147 } else {
148 fBackgroundTasks.add(wrapper);
149 }
150 }
151
152 /**
153 * Timer task to trigger scheduleNext()
154 */
155 private class SchedSwitch extends TimerTask {
156
157 SchedSwitch() {
158 }
159
160 @Override
161 public void run() {
96b353c5
FC
162 scheduleNext();
163 }
11252342
AM
164 }
165
166 /**
167 * Executes the next pending request, if applicable.
168 */
169 protected synchronized void scheduleNext() {
170 if (!isShutdown()) {
306586b1
SD
171 if (fActiveTask == null) {
172 schedule();
173 } else if (fActiveTask.getExecType() == ExecutionType.FOREGROUND) {
174 if (fActiveTask.getThread().isCompleted()) {
6dcda2b7 175 fActiveTask = null;
306586b1
SD
176 schedule();
177 } else {
178 if (hasTasks()) {
179 fActiveTask.getThread().suspend();
180 fForegroundTasks.add(fActiveTask);
181 schedule();
182 }
183 }
184
185 } else if (fActiveTask.getExecType() == ExecutionType.BACKGROUND) {
186 if (fActiveTask.getThread().isCompleted()) {
6dcda2b7 187 fActiveTask = null;
306586b1
SD
188 schedule();
189 } else {
190 if (hasTasks()) {
191 fActiveTask.getThread().suspend();
192 fBackgroundTasks.add(fActiveTask);
193 schedule();
194 }
195 }
11252342
AM
196 }
197 }
198 }
8c8bf09f 199
96b353c5
FC
200 /**
201 * Stops the executor
202 */
203 public synchronized void stop() {
661b21a1
PT
204 if (fTimerTask != null) {
205 fTimerTask.cancel();
206 }
207
208 if (fTimer != null) {
209 fTimer.cancel();
210 }
b67f3f7c 211
96b353c5
FC
212 if (fActiveTask != null) {
213 fActiveTask.cancel();
214 }
215
306586b1
SD
216 while ((fActiveTask = fForegroundTasks.poll()) != null) {
217 fActiveTask.cancel();
218 }
219 while ((fActiveTask = fBackgroundTasks.poll()) != null) {
96b353c5
FC
220 fActiveTask.cancel();
221 }
222
223 fExecutor.shutdown();
224 if (TmfCoreTracer.isComponentTraced()) {
225 TmfCoreTracer.trace(fExecutor + " terminated"); //$NON-NLS-1$
226 }
227 }
228
306586b1
SD
229 // ------------------------------------------------------------------------
230 // Helper methods
231 // ------------------------------------------------------------------------
232
233 /**
234 * Determine which type of request (foreground or background) we schedule
235 * next
236 */
237 private void schedule() {
238 if (!fForegroundTasks.isEmpty()) {
239 scheduleNextForeground();
240 } else {
241 scheduleNextBackground();
242 }
243 }
244
245 /**
246 * Schedule the next foreground request
247 */
248 private void scheduleNextForeground() {
249 if (fForegroundCycle < FOREGROUND_SLOT || fBackgroundTasks.isEmpty()) {
250 ++fForegroundCycle;
251 fActiveTask = fForegroundTasks.poll();
252 executefActiveTask();
253 } else {
254 fActiveTask = null;
255 scheduleNextBackground();
256 }
257 }
258
259 /**
260 * Schedule the next background request
261 */
262 private void scheduleNextBackground() {
263 fForegroundCycle = 0;
264 if (!fBackgroundTasks.isEmpty()) {
265 fActiveTask = fBackgroundTasks.poll();
266 executefActiveTask();
267 }
268 }
269
270 /**
271 * Execute or resume the active task
272 */
273 private void executefActiveTask() {
274 if (fActiveTask.getThread().isPaused()) {
275 fActiveTask.getThread().resume();
276 } else {
277 fExecutor.execute(fActiveTask);
278 }
279 }
280
281 /**
282 * Check if the scheduler has tasks
283 */
284 private boolean hasTasks() {
285 return !(fForegroundTasks.isEmpty() && fBackgroundTasks.isEmpty());
286 }
287
11252342
AM
288 // ------------------------------------------------------------------------
289 // Object
290 // ------------------------------------------------------------------------
5c00c0b7 291
11252342 292 @Override
3b38ea61 293 @SuppressWarnings("nls")
11252342
AM
294 public String toString() {
295 return "[TmfRequestExecutor(" + fExecutorName + ")]";
296 }
8c8bf09f
ASL
297
298}
This page took 0.086439 seconds and 5 git commands to generate.