1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.lib;
12
13 import java.util.concurrent.Semaphore;
14 import java.util.concurrent.atomic.AtomicInteger;
15 import java.util.concurrent.locks.ReentrantLock;
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 public class ThreadSafeProgressMonitor implements ProgressMonitor {
31 private final ProgressMonitor pm;
32
33 private final ReentrantLock lock;
34
35 private final Thread mainThread;
36
37 private final AtomicInteger workers;
38
39 private final AtomicInteger pendingUpdates;
40
41 private final Semaphore process;
42
43
44
45
46
47
48
49 public ThreadSafeProgressMonitor(ProgressMonitor pm) {
50 this.pm = pm;
51 this.lock = new ReentrantLock();
52 this.mainThread = Thread.currentThread();
53 this.workers = new AtomicInteger(0);
54 this.pendingUpdates = new AtomicInteger(0);
55 this.process = new Semaphore(0);
56 }
57
58
59 @Override
60 public void start(int totalTasks) {
61 if (!isMainThread())
62 throw new IllegalStateException();
63 pm.start(totalTasks);
64 }
65
66
67 @Override
68 public void beginTask(String title, int totalWork) {
69 if (!isMainThread())
70 throw new IllegalStateException();
71 pm.beginTask(title, totalWork);
72 }
73
74
75
76
77 public void startWorker() {
78 startWorkers(1);
79 }
80
81
82
83
84
85
86
87 public void startWorkers(int count) {
88 workers.addAndGet(count);
89 }
90
91
92
93
94 public void endWorker() {
95 if (workers.decrementAndGet() == 0)
96 process.release();
97 }
98
99
100
101
102
103
104
105 public void pollForUpdates() {
106 assert isMainThread();
107 doUpdates();
108 }
109
110
111
112
113
114
115
116
117
118
119
120 public void waitForCompletion() throws InterruptedException {
121 assert isMainThread();
122 while (0 < workers.get()) {
123 doUpdates();
124 process.acquire();
125 }
126 doUpdates();
127 }
128
129 private void doUpdates() {
130 int cnt = pendingUpdates.getAndSet(0);
131 if (0 < cnt)
132 pm.update(cnt);
133 }
134
135
136 @Override
137 public void update(int completed) {
138 if (0 == pendingUpdates.getAndAdd(completed))
139 process.release();
140 }
141
142
143 @Override
144 public boolean isCancelled() {
145 lock.lock();
146 try {
147 return pm.isCancelled();
148 } finally {
149 lock.unlock();
150 }
151 }
152
153
154 @Override
155 public void endTask() {
156 if (!isMainThread())
157 throw new IllegalStateException();
158 pm.endTask();
159 }
160
161 private boolean isMainThread() {
162 return Thread.currentThread() == mainThread;
163 }
164 }