Merge branch 'master' of git.labs.intellij.net:idea/community
[idea/community.git] / platform / platform-api / src / com / intellij / openapi / progress / BackgroundTaskQueue.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package com.intellij.openapi.progress;
18
19 import com.intellij.openapi.application.ApplicationManager;
20 import com.intellij.openapi.application.ModalityState;
21 import com.intellij.openapi.project.Project;
22 import org.jetbrains.annotations.NotNull;
23
24 import java.util.LinkedList;
25 import java.util.Queue;
26
27 /**
28  * @author yole
29  */
30 @SomeQueue
31 public class BackgroundTaskQueue {
32   private final Project myProject;
33   private final Queue<Task> myQueue = new LinkedList<Task>();
34   private boolean myHasActiveTask = false;
35   private Task.Backgroundable myRunnerTask;
36
37   public BackgroundTaskQueue(String title) {
38     this(null, title);
39   }
40
41   public BackgroundTaskQueue(Project project, String title) {
42     myProject = project;
43     myRunnerTask = new Task.Backgroundable(project, title) {
44       public void run(@NotNull final ProgressIndicator indicator) {
45         while (true) {
46           final Task task;
47
48           synchronized(myQueue) {
49             myHasActiveTask = true;
50             task = myQueue.poll();
51             if (task == null) {
52               myHasActiveTask = false;
53               return;
54             }
55           }
56
57           indicator.setText(task.getTitle());
58           try {
59             task.run(indicator);
60           } catch (ProcessCanceledException e) {
61             //ok
62           }
63
64           ApplicationManager.getApplication().invokeLater(new Runnable() {
65             public void run() {
66               if (myProject == null || !myProject.isDisposed()) {
67                 task.onSuccess();
68               }
69             }
70           }, ModalityState.NON_MODAL);
71         }
72       }
73     };
74   }
75
76   public void run(Task.Backgroundable task) {
77     if (ApplicationManager.getApplication().isUnitTestMode()) {
78       task.run(new EmptyProgressIndicator());
79       task.onSuccess();
80     }
81     else if (task.isConditionalModal() && !task.shouldStartInBackground()) {
82       ProgressManager.getInstance().run(task);
83     }
84     else {
85       boolean hadActiveTask;
86       synchronized (myQueue) {
87         hadActiveTask = myHasActiveTask;
88         myQueue.offer(task);
89         myHasActiveTask = true;
90       }
91       if (!hadActiveTask) {
92         if (ApplicationManager.getApplication().isDispatchThread()) {
93           ProgressManager.getInstance().run(myRunnerTask);
94         }
95         else {
96           ApplicationManager.getApplication().invokeLater(new Runnable() {
97             public void run() {
98               if (myProject == null || !myProject.isDisposed()) {
99                 ProgressManager.getInstance().run(myRunnerTask);
100               }
101             }
102           });
103         }
104       }
105     }
106   }
107 }