ComponentWithBrowseButton - optional remove listener on hide
[fedora-idea.git] / platform / platform-impl / src / com / intellij / concurrency / JobImpl.java
blobeb82ecf97ae37f5e16d3da8a5768801802e81113
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * @author max
20 package com.intellij.concurrency;
22 import com.intellij.openapi.application.Application;
23 import com.intellij.openapi.application.ApplicationManager;
24 import com.intellij.util.containers.ContainerUtil;
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.concurrent.*;
30 public class JobImpl<T> implements Job<T> {
31 private final String myTitle;
32 private final List<Callable<T>> myTasks = ContainerUtil.createEmptyCOWList();
33 private final long myJobIndex = JobSchedulerImpl.currentJobIndex();
34 private final int myPriority;
35 private final List<PrioritizedFutureTask<T>> myFutures = ContainerUtil.createEmptyCOWList();
36 private volatile boolean myCanceled = false;
38 public JobImpl(String title, int priority) {
39 myTitle = title;
40 myPriority = priority;
43 public String getTitle() {
44 return myTitle;
47 public void addTask(Callable<T> task) {
48 checkNotStarted();
50 myTasks.add(task);
53 public void addTask(Runnable task, T result) {
54 addTask(Executors.callable(task, result));
57 public void addTask(Runnable task) {
58 addTask(Executors.callable(task, (T)null));
61 public List<T> scheduleAndWaitForResults() throws Throwable {
62 checkCanSchedule();
63 final Application application = ApplicationManager.getApplication();
64 boolean callerHasReadAccess = application != null && application.isReadAccessAllowed();
66 createFutures(callerHasReadAccess, false);
68 // Don't bother scheduling if we only have one processor or only one task
69 if (JobSchedulerImpl.CORES_COUNT >= 2 && myFutures.size() >= 2) {
70 for (PrioritizedFutureTask<T> future : myFutures) {
71 JobSchedulerImpl.execute(future);
75 // http://gafter.blogspot.com/2006/11/thread-pool-puzzler.html
76 for (PrioritizedFutureTask<T> future : myFutures) {
77 future.run();
80 return waitForTermination();
83 private void createFutures(boolean callerHasReadAccess, final boolean reportExceptions) {
84 int startTaskIndex = JobSchedulerImpl.currentTaskIndex();
85 for (final Callable<T> task : myTasks) {
86 final PrioritizedFutureTask<T> future = new PrioritizedFutureTask<T>(task, myJobIndex, startTaskIndex++, myPriority, callerHasReadAccess,
87 reportExceptions);
88 myFutures.add(future);
92 public List<T> waitForTermination() throws Throwable {
93 List<T> results = new ArrayList<T>(myFutures.size());
95 Throwable ex = null;
96 for (Future<T> f : myFutures) {
97 try {
98 results.add(f.get());
100 catch (CancellationException ignore) {
102 catch (ExecutionException e) {
103 cancel();
105 Throwable cause = e.getCause();
106 if (cause != null) {
107 ex = cause;
112 // Future.get() exits when currently running is canceled, thus awaiter may get control before spawned tasks actually terminated,
113 // that's why additional join logic.
114 for (PrioritizedFutureTask<T> future : myFutures) {
115 future.awaitTermination();
118 if (ex != null) throw ex;
120 return results;
123 public void cancel() {
124 checkScheduled();
125 if (myCanceled) return;
126 myCanceled = true;
128 for (Future<T> future : myFutures) {
129 future.cancel(false);
133 public boolean isCanceled() {
134 checkScheduled();
135 return myCanceled;
138 public void schedule() {
139 checkCanSchedule();
141 createFutures(false, true);
143 for (PrioritizedFutureTask<T> future : myFutures) {
144 JobSchedulerImpl.execute(future);
148 public boolean isDone() {
149 checkScheduled();
151 for (Future<T> future : myFutures) {
152 if (!future.isDone()) return false;
155 return true;
158 private void checkCanSchedule() {
159 checkNotStarted();
160 if (myTasks.isEmpty()) {
161 throw new IllegalStateException("No tasks to run. You can't schedule a job which has no tasks");
165 private void checkNotStarted() {
166 if (!myFutures.isEmpty()) {
167 throw new IllegalStateException("Already running. You can't call this method for a job which is already scheduled");
171 private void checkScheduled() {
172 if (myFutures.isEmpty()) {
173 throw new IllegalStateException("Cannot call this method for not yet started job");