1 /******************************************************************************* 2 * Copyright (c) 2003, 2012 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.core.runtime.jobs; 15 16 import org.eclipse.core.runtime.IProgressMonitor; 17 import org.eclipse.core.runtime.OperationCanceledException; 18 19 /** 20 * The job manager provides facilities for scheduling, querying, and maintaining jobs 21 * and locks. In particular, the job manager provides the following services: 22 * <ul> 23 * <li>Maintains a queue of jobs that are waiting to be run. Items can be added to 24 * the queue using the <code>schedule</code> method.</li> 25 * <li>Allows manipulation of groups of jobs called job families. Job families can 26 * be canceled, put to sleep, or woken up atomically. There is also a mechanism 27 * for querying the set of known jobs in a given family.</li> 28 * <li>Allows listeners to find out about progress on running jobs, and to find out 29 * when jobs have changed states.</li> 30 * <li>Provides a factory for creating lock objects. Lock objects are smart monitors 31 * that have strategies for avoiding deadlock.</li> 32 * <li>Provide feedback to a client that is waiting for a given job or family of jobs 33 * to complete.</li> 34 * </ul> 35 * 36 * @see Job 37 * @see ILock 38 * @since 3.0 39 * @noimplement This interface is not intended to be implemented by clients. 40 * @noextend This interface is not intended to be extended by clients. 41 */ 42 public interface IJobManager { 43 /** 44 * A system property key indicating whether the job manager should create 45 * job threads as daemon threads. Set to <code>true</code> to force all worker 46 * threads to be created as daemon threads. Set to <code>false</code> to force 47 * all worker threads to be created as non-daemon threads. 48 * @since 3.3 49 */ 50 String PROP_USE_DAEMON_THREADS = "eclipse.jobs.daemon"; //$NON-NLS-1$ 51 52 /** 53 * Registers a job listener with the job manager. 54 * Has no effect if an identical listener is already registered. 55 * 56 * @param listener the listener to be added 57 * @see #removeJobChangeListener(IJobChangeListener) 58 * @see IJobChangeListener 59 */ addJobChangeListener(IJobChangeListener listener)60 void addJobChangeListener(IJobChangeListener listener); 61 62 /** 63 * Begins applying this rule in the calling thread. If the rule conflicts with another 64 * rule currently running in another thread, this method blocks until there are 65 * no conflicting rules. Calls to <code>beginRule</code> must eventually be followed 66 * by a matching call to <code>endRule</code> in the same thread and with the identical 67 * rule instance. 68 * <p> 69 * Rules can be nested only if the rule for the inner <code>beginRule</code> 70 * is contained within the rule for the outer <code>beginRule</code>. Rule containment 71 * is tested with the API method <code>ISchedulingRule.contains</code>. Also, begin/end 72 * pairs must be strictly nested. Only the rule that has most recently begun 73 * can be ended at any given time. 74 * <p> 75 * A rule of <code>null</code> can be used, but will be ignored for scheduling 76 * purposes. The outermost non-null rule in the thread will be used for scheduling. A 77 * <code>null</code> rule that is begun must still be ended. 78 * <p> 79 * If this method is called from within a job that has a scheduling rule, the 80 * given rule must also be contained within the rule for the running job. 81 * <p> 82 * Note that <code>endRule</code> must be called even if <code>beginRule</code> fails. 83 * The recommended usage is: 84 * <pre> 85 * final ISchedulingRule rule = ...; 86 * try { 87 * manager.beginRule(rule, monitor); 88 * } finally { 89 * manager.endRule(rule); 90 * } 91 * </pre> 92 * 93 * @param rule the rule to begin applying in this thread, or <code>null</code> 94 * @param monitor a progress monitor, or <code>null</code> if progress 95 * reporting and cancellation are not desired 96 * @throws IllegalArgumentException if the rule is not strictly nested within 97 * all other rules currently active for this thread 98 * @throws OperationCanceledException if the supplied monitor reports cancelation 99 * before the rule becomes available 100 * @see ISchedulingRule#contains(ISchedulingRule) 101 */ beginRule(ISchedulingRule rule, IProgressMonitor monitor)102 void beginRule(ISchedulingRule rule, IProgressMonitor monitor); 103 104 /** 105 * Cancels all jobs in the given job family. Jobs in the family that are currently waiting 106 * will be removed from the queue. Sleeping jobs will be discarded without having 107 * a chance to wake up. Currently executing jobs will be asked to cancel but there 108 * is no guarantee that they will do so. 109 * 110 * @param family the job family to cancel, or <code>null</code> to cancel all jobs 111 * @see Job#belongsTo(Object) 112 */ cancel(Object family)113 void cancel(Object family); 114 115 /** 116 * Returns a progress monitor that can be used to provide aggregated progress 117 * feedback on a set of running jobs. A user interface will typically group all 118 * jobs in a progress group together, providing progress feedback for individual 119 * jobs as well as aggregated progress for the entire group. Jobs in the group 120 * may be run sequentially, in parallel, or some combination of the two. 121 * <p> 122 * Recommended usage (this snippet runs two jobs in sequence in a single 123 * progress group): 124 * 125 * <pre> 126 * Job parseJob, compileJob; 127 * IProgressMonitor pm = Job.getJobManager().createProgressGroup(); 128 * try { 129 * pm.beginTask("Building", 10); 130 * parseJob.setProgressGroup(pm, 5); 131 * parseJob.schedule(); 132 * compileJob.setProgressGroup(pm, 5); 133 * compileJob.schedule(); 134 * parseJob.join(); 135 * compileJob.join(); 136 * } finally { 137 * pm.done(); 138 * } 139 * </pre> 140 * 141 * @see Job#setProgressGroup(IProgressMonitor, int) 142 * @see IProgressMonitor 143 * @return a progress monitor 144 */ createProgressGroup()145 IProgressMonitor createProgressGroup(); 146 147 /** 148 * Returns the scheduling rule currently held by this thread, or <code>null</code> 149 * if the current thread does not hold any scheduling rule. 150 * <p> 151 * If this method is called from within the scope of a running job with a non-null 152 * scheduling rule, then this method is equivalent to calling <code>currentJob().getRule()</code>. 153 * Otherwise, this method will return the first scheduling rule obtained by this 154 * thread via {@link #beginRule(ISchedulingRule, IProgressMonitor)} that has not 155 * yet had a corresponding call to {@link #endRule(ISchedulingRule)}. 156 * </p> 157 * 158 * @return the current rule or <code>null</code> 159 * @since 3.5 160 */ currentRule()161 ISchedulingRule currentRule(); 162 163 /** 164 * Returns the job that is currently running in this thread, or <code>null</code> if there 165 * is no currently running job. 166 * 167 * @return the job or <code>null</code> 168 */ currentJob()169 Job currentJob(); 170 171 /** 172 * Ends the application of a rule to the calling thread. Calls to <code>endRule</code> 173 * must be preceded by a matching call to <code>beginRule</code> in the same thread 174 * with an identical rule instance. 175 * <p> 176 * Rules can be nested only if the rule for the inner <code>beginRule</code> 177 * is contained within the rule for the outer <code>beginRule</code>. Also, begin/end 178 * pairs must be strictly nested. Only the rule that has most recently begun 179 * can be ended at any given time. 180 * 181 * @param rule the rule to end applying in this thread 182 * @throws IllegalArgumentException if this method is called on a rule for which 183 * there is no matching begin, or that does not match the most recent begin. 184 * @see ISchedulingRule#contains(ISchedulingRule) 185 */ endRule(ISchedulingRule rule)186 void endRule(ISchedulingRule rule); 187 188 /** 189 * Returns all waiting, executing and sleeping jobs belonging 190 * to the given family. If no jobs are found, an empty array is returned. 191 * 192 * @param family the job family to find, or <code>null</code> to find all jobs 193 * @return the job array 194 * @see Job#belongsTo(Object) 195 */ find(Object family)196 Job[] find(Object family); 197 198 /** 199 * Returns whether the job manager is currently idle. The job manager is 200 * idle if no jobs are currently running or waiting to run. 201 * 202 * @return <code>true</code> if the job manager is idle, and 203 * <code>false</code> otherwise 204 * @since 3.1 205 */ isIdle()206 boolean isIdle(); 207 208 /** 209 * Returns whether the job manager is currently suspended. 210 * 211 * @return <code>true</code> if the job manager is suspended, and 212 * <code>false</code> otherwise 213 * @since 3.4 214 * @see #suspend() 215 * @see #resume() 216 */ isSuspended()217 boolean isSuspended(); 218 219 /** 220 * Waits until all jobs of the given family are finished. This method will block the 221 * calling thread until all such jobs have finished executing, or until this thread is 222 * interrupted. If there are no jobs in the family that are currently waiting, running, 223 * or sleeping, this method returns immediately. Feedback on how the join is 224 * progressing is provided to a progress monitor. 225 * <p> 226 * If this method is called while the job manager is suspended, only jobs 227 * that are currently running will be joined; Once there are no jobs 228 * in the family in the {@link Job#RUNNING} state, this method returns. 229 * </p> 230 * <p> 231 * Note that there is a deadlock risk when using join. If the calling thread owns 232 * a lock or object monitor that the joined thread is waiting for, deadlock 233 * will occur. This method can also result in starvation of the current thread if 234 * another thread continues to add jobs of the given family, or if a 235 * job in the given family reschedules itself in an infinite loop. 236 * </p> 237 * 238 * @param family the job family to join, or <code>null</code> to join all jobs. 239 * @param monitor Progress monitor for reporting progress on how the 240 * wait is progressing, or <code>null</code> if no progress monitoring is required. 241 * @exception InterruptedException if this thread is interrupted while waiting 242 * @exception OperationCanceledException if the progress monitor is canceled while waiting 243 * @see Job#belongsTo(Object) 244 * @see #suspend() 245 */ join(Object family, IProgressMonitor monitor)246 void join(Object family, IProgressMonitor monitor) throws InterruptedException, OperationCanceledException; 247 248 /** 249 * Creates a new lock object. All lock objects supplied by the job manager 250 * know about each other and will always avoid circular deadlock amongst 251 * themselves. 252 * 253 * @return the new lock object 254 */ newLock()255 ILock newLock(); 256 257 /** 258 * Removes a job listener from the job manager. 259 * Has no effect if an identical listener is not already registered. 260 * 261 * @param listener the listener to be removed 262 * @see #addJobChangeListener(IJobChangeListener) 263 * @see IJobChangeListener 264 */ removeJobChangeListener(IJobChangeListener listener)265 void removeJobChangeListener(IJobChangeListener listener); 266 267 /** 268 * Resumes execution of jobs after a previous <code>suspend</code>. All 269 * jobs that were sleeping or waiting prior to the suspension, or that were 270 * scheduled while the job manager was suspended, will now be eligible 271 * for execution. 272 * <p> 273 * Calling this method on a rule that is not suspended has no effect. If another 274 * thread also owns the rule at the time this method is called, then the rule will 275 * not be resumed until all threads have released the rule. 276 * 277 * @deprecated This method is not safe and should not be used. 278 * Suspending a scheduling rule violates the thread safety 279 * of clients that use scheduling rules as a mutual exclusion mechanism, 280 * and can result in concurrency problems in all clients that use the suspended rule. 281 * @see #suspend(ISchedulingRule, IProgressMonitor) 282 */ resume(ISchedulingRule rule)283 @Deprecated void resume(ISchedulingRule rule); 284 285 /** 286 * Resumes execution of jobs after a previous <code>suspend</code>. All 287 * jobs that were sleeping or waiting prior to the suspension, or that were 288 * scheduled while the job manager was suspended, will now be eligible 289 * for execution. 290 * <p> 291 * Calling <code>resume</code> when the job manager is not suspended 292 * has no effect. 293 * 294 * @see #suspend() 295 * @see #isSuspended() 296 */ resume()297 void resume(); 298 299 /** 300 * Provides a hook that is notified whenever a thread is about to wait on a lock, 301 * or when a thread is about to release a lock. This hook must only be set once. 302 * <p> 303 * This method is for internal use by the platform-related plug-ins. 304 * Clients should not call this method. 305 * </p> 306 * @see LockListener 307 */ setLockListener(LockListener listener)308 void setLockListener(LockListener listener); 309 310 /** 311 * Registers a progress provider with the job manager. If there was a 312 * provider already registered, it is replaced. 313 * <p> 314 * This method is intended for use by the currently executing Eclipse application. 315 * Plug-ins outside the currently running application should not call this method. 316 * </p> 317 * 318 * @param provider the new provider, or <code>null</code> if no progress 319 * is needed 320 */ setProgressProvider(ProgressProvider provider)321 void setProgressProvider(ProgressProvider provider); 322 323 /** 324 * Suspends execution of all jobs. Jobs that are already running 325 * when this method is invoked will complete as usual, but all sleeping and 326 * waiting jobs will not be executed until the job manager is resumed. 327 * <p> 328 * The job manager will remain suspended until a subsequent call to 329 * <code>resume</code>. Further calls to <code>suspend</code> 330 * when the job manager is already suspended are ignored. 331 * <p> 332 * All attempts to join sleeping and waiting jobs while the job manager is 333 * suspended will return immediately. 334 * <p> 335 * Note that this very powerful function should be used with extreme caution. 336 * Suspending the job manager will prevent all jobs in the system from executing, 337 * which may have adverse affects on components that are relying on 338 * execution of jobs. The job manager should never be suspended without intent 339 * to resume execution soon afterwards. 340 * 341 * @see #resume() 342 * @see #join(Object, IProgressMonitor) 343 * @see #isSuspended() 344 */ suspend()345 void suspend(); 346 347 /** 348 * Defers execution of all jobs with scheduling rules that conflict with the 349 * given rule. The caller will be blocked until all currently executing jobs with 350 * conflicting rules are completed. Conflicting jobs that are sleeping or waiting at 351 * the time this method is called will not be executed until the rule is resumed. 352 * <p> 353 * While a rule is suspended, all calls to <code>beginRule</code> and 354 * <code>endRule</code> on a suspended rule will not block the caller. 355 * The rule remains suspended until a subsequent call to 356 * <code>resume(ISchedulingRule)</code> with the identical rule instance. 357 * Further calls to <code>suspend</code> with an identical rule prior to calling 358 * <code>resume</code> are ignored. 359 * </p> 360 * <p> 361 * This method is long-running; progress and cancelation are provided by 362 * the given progress monitor. In the case of cancelation, the rule will 363 * not be suspended. 364 * </p> 365 * Note: this very powerful function should be used with extreme caution. 366 * Suspending rules will prevent jobs in the system from executing, which may 367 * have adverse effects on components that are relying on execution of jobs. 368 * The job manager should never be suspended without intent to resume 369 * execution soon afterwards. Deadlock will result if the thread responsible 370 * for resuming the rule attempts to join a suspended job. 371 * 372 * @deprecated This method is not safe and should not be used. 373 * Suspending a scheduling rule violates the thread safety 374 * of clients that use scheduling rules as a mutual exclusion mechanism, 375 * and can result in concurrency problems in all clients that use the suspended rule. 376 * @param rule The scheduling rule to suspend. Must not be <code>null</code>. 377 * @param monitor a progress monitor, or <code>null</code> if progress 378 * reporting is not desired 379 * @exception OperationCanceledException if the operation is canceled. 380 * Cancelation can occur even if no progress monitor is provided. 381 * @see #resume(ISchedulingRule) 382 */ suspend(ISchedulingRule rule, IProgressMonitor monitor)383 @Deprecated void suspend(ISchedulingRule rule, IProgressMonitor monitor); 384 385 /** 386 * Requests that all jobs in the given job family be suspended. Jobs currently 387 * waiting to be run will be removed from the queue and moved into the 388 * <code>SLEEPING</code> state. Jobs that have been put to sleep 389 * will remain in that state until either resumed or canceled. This method has 390 * no effect on jobs that are not currently waiting to be run. 391 * <p> 392 * Sleeping jobs can be resumed using <code>wakeUp</code>. 393 * 394 * @param family the job family to sleep, or <code>null</code> to sleep all jobs. 395 * @see Job#belongsTo(Object) 396 */ sleep(Object family)397 void sleep(Object family); 398 399 /** 400 * Transfers ownership of a scheduling rule to another thread. The identical 401 * scheduling rule must currently be owned by the calling thread as a result of 402 * a previous call to <code>beginRule</code>. The destination thread must 403 * not already own a scheduling rule. 404 * <p> 405 * Calling this method is equivalent to atomically calling <code>endRule</code> 406 * in the calling thread followed by an immediate <code>beginRule</code> in 407 * the destination thread. The destination thread is responsible for subsequently 408 * calling <code>endRule</code> when it is finished using the rule. 409 * <p> 410 * This method has no effect when the destination thread is the same as the 411 * calling thread. 412 * 413 * @param rule The scheduling rule to transfer 414 * @param destinationThread The new owner for the transferred rule. 415 * @since 3.1 416 */ transferRule(ISchedulingRule rule, Thread destinationThread)417 void transferRule(ISchedulingRule rule, Thread destinationThread); 418 419 /** 420 * Resumes scheduling of all sleeping jobs in the given family. This method 421 * has no effect on jobs in the family that are not currently sleeping. 422 * 423 * @param family the job family to wake up, or <code>null</code> to wake up all jobs 424 * @see Job#belongsTo(Object) 425 */ wakeUp(Object family)426 void wakeUp(Object family); 427 } 428