tmf: Fix regression in event requests
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / internal / tmf / core / request / TmfRequestExecutor.java
1 /*******************************************************************************
2 * Copyright (c) 2009, 2010, 2012 Ericsson
3 *
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
8 *
9 * Contributors:
10 * Francois Chouinard - Initial API and implementation
11 * Francois Chouinard - Added support for pre-emption
12 *******************************************************************************/
13
14 package org.eclipse.linuxtools.internal.tmf.core.request;
15
16 import java.util.Queue;
17 import java.util.concurrent.ArrayBlockingQueue;
18 import java.util.concurrent.Executor;
19 import java.util.concurrent.ExecutorService;
20 import java.util.concurrent.Executors;
21
22 import org.eclipse.linuxtools.internal.tmf.core.TmfCoreTracer;
23 import org.eclipse.linuxtools.internal.tmf.core.component.TmfEventThread;
24 import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest.ExecutionType;
25
26 /**
27 * A simple, straightforward request executor.
28 *
29 * @author Francois Chouinard
30 * @version 1.1
31 */
32 public class TmfRequestExecutor implements Executor {
33
34 // ------------------------------------------------------------------------
35 // Attributes
36 // ------------------------------------------------------------------------
37
38 // The request executor
39 private final ExecutorService fExecutor = Executors.newFixedThreadPool(2);
40 private final String fExecutorName;
41
42 // The request queues
43 private final Queue<TmfEventThread> fHighPriorityTasks = new ArrayBlockingQueue<TmfEventThread>(100);
44 private final Queue<TmfEventThread> fLowPriorityTasks = new ArrayBlockingQueue<TmfEventThread>(100);
45
46 // The tasks
47 private TmfEventThread fActiveTask;
48 private TmfEventThread fSuspendedTask;
49
50 // ------------------------------------------------------------------------
51 // Constructors
52 // ------------------------------------------------------------------------
53
54 /**
55 * Default constructor
56 */
57 public TmfRequestExecutor() {
58 String canonicalName = fExecutor.getClass().getCanonicalName();
59 fExecutorName = canonicalName.substring(canonicalName.lastIndexOf('.') + 1);
60 if (TmfCoreTracer.isComponentTraced()) {
61 TmfCoreTracer.trace(fExecutor + " created"); //$NON-NLS-1$
62 }
63 }
64
65 /**
66 * Standard constructor
67 *
68 * @param executor The executor service to use
69 */
70 @Deprecated
71 public TmfRequestExecutor(ExecutorService executor) {
72 this();
73 }
74
75 // ------------------------------------------------------------------------
76 // Getters
77 // ------------------------------------------------------------------------
78
79 /**
80 * @return the number of pending requests
81 */
82 @Deprecated
83 public synchronized int getNbPendingRequests() {
84 return fHighPriorityTasks.size() + fLowPriorityTasks.size();
85 }
86
87 /**
88 * @return the shutdown state (i.e. if it is accepting new requests)
89 */
90 public synchronized boolean isShutdown() {
91 return fExecutor.isShutdown();
92 }
93
94 /**
95 * @return the termination state
96 */
97 public synchronized boolean isTerminated() {
98 return fExecutor.isTerminated();
99 }
100
101 // ------------------------------------------------------------------------
102 // Operations
103 // ------------------------------------------------------------------------
104
105 /* (non-Javadoc)
106 * @see java.util.concurrent.Executor#execute(java.lang.Runnable)
107 */
108 @Override
109 public synchronized void execute(final Runnable command) {
110
111 // We are expecting MyEventThread:s
112 if (!(command instanceof TmfEventThread)) {
113 // TODO: Log an error
114 return;
115 }
116
117 // Wrap the thread in a MyThread
118 TmfEventThread thread = (TmfEventThread) command;
119 TmfEventThread wrapper = new TmfEventThread(thread) {
120 @Override
121 public void run() {
122 try {
123 command.run();
124 } finally {
125 scheduleNext();
126 }
127 }
128 };
129
130 // Add the thread to the appropriate queue
131 ExecutionType priority = thread.getExecType();
132 (priority == ExecutionType.FOREGROUND ? fHighPriorityTasks : fLowPriorityTasks).offer(wrapper);
133
134 // Schedule or preempt as appropriate
135 if (fActiveTask == null) {
136 scheduleNext();
137 } else if (priority == ExecutionType.FOREGROUND && priority != fActiveTask.getExecType()) {
138 fActiveTask.getThread().suspend();
139 fSuspendedTask = fActiveTask;
140 scheduleNext();
141 }
142 }
143
144 /**
145 * Executes the next pending request, if applicable.
146 */
147 protected synchronized void scheduleNext() {
148 if (!isShutdown()) {
149 if ((fActiveTask = fHighPriorityTasks.poll()) != null) {
150 fExecutor.execute(fActiveTask);
151 } else if (fSuspendedTask != null) {
152 fActiveTask = fSuspendedTask;
153 fSuspendedTask = null;
154 fActiveTask.getThread().resume();
155 } else if ((fActiveTask = fLowPriorityTasks.poll()) != null) {
156 fExecutor.execute(fActiveTask);
157 }
158 }
159 }
160
161 /**
162 * Stops the executor
163 */
164 public synchronized void stop() {
165 if (fActiveTask != null) {
166 fActiveTask.cancel();
167 }
168
169 while ((fActiveTask = fHighPriorityTasks.poll()) != null) {
170 fActiveTask.cancel();
171 }
172
173 fExecutor.shutdown();
174 if (TmfCoreTracer.isComponentTraced()) {
175 TmfCoreTracer.trace(fExecutor + " terminated"); //$NON-NLS-1$
176 }
177 }
178
179 // ------------------------------------------------------------------------
180 // Object
181 // ------------------------------------------------------------------------
182
183 @Override
184 @SuppressWarnings("nls")
185 public String toString() {
186 return "[TmfRequestExecutor(" + fExecutorName + ")]";
187 }
188
189 }
This page took 0.034002 seconds and 5 git commands to generate.