25 import java.util.concurrent.TimeUnit; |
25 import java.util.concurrent.TimeUnit; |
26 import java.util.concurrent.TimeoutException; |
26 import java.util.concurrent.TimeoutException; |
27 import java.util.concurrent.atomic.AtomicInteger; |
27 import java.util.concurrent.atomic.AtomicInteger; |
28 import java.util.concurrent.locks.LockSupport; |
28 import java.util.concurrent.locks.LockSupport; |
29 |
29 |
|
30 import jdk.testlibrary.LockFreeLogManager; |
|
31 |
30 /** |
32 /** |
31 * ThreadStateController allows a thread to request this thread to transition |
33 * ThreadStateController allows a thread to request this thread to transition |
32 * to a specific thread state. The {@linkplain #transitionTo request} is |
34 * to a specific thread state. The {@linkplain #transitionTo request} is |
33 * a blocking call that the calling thread will wait until this thread is about |
35 * a blocking call that the calling thread will wait until this thread is about |
34 * going to the new state. Only one request of state transition at a time |
36 * going to the new state. Only one request of state transition at a time |
117 sum += x - r; |
123 sum += x - r; |
118 } |
124 } |
119 break; |
125 break; |
120 } |
126 } |
121 case S_BLOCKED: { |
127 case S_BLOCKED: { |
122 System.out.format("%d: %s is going to block (interations %d)%n", |
128 log("%d: %s is going to block (iterations %d)%n", |
123 getId(), getName(), iterations.get()); |
129 getId(), getName(), iterations.get()); |
124 stateChange(nextState); |
130 stateChange(nextState); |
125 // going to block on lock |
131 // going to block on lock |
126 synchronized (lock) { |
132 synchronized (lock) { |
127 System.out.format("%d: %s acquired the lock (interations %d)%n", |
133 log("%d: %s acquired the lock (iterations %d)%n", |
128 getId(), getName(), iterations.get()); |
134 getId(), getName(), iterations.get()); |
129 try { |
135 try { |
130 // this thread has escaped the BLOCKED state |
136 // this thread has escaped the BLOCKED state |
131 // release the lock and a short wait before continue |
137 // release the lock and a short wait before continue |
132 lock.wait(10); |
138 lock.wait(10); |
133 } catch (InterruptedException e) { |
139 } catch (InterruptedException e) { |
137 } |
143 } |
138 break; |
144 break; |
139 } |
145 } |
140 case S_WAITING: { |
146 case S_WAITING: { |
141 synchronized (lock) { |
147 synchronized (lock) { |
142 System.out.format("%d: %s is going to waiting (interations %d interrupted %d)%n", |
148 log("%d: %s is going to waiting (iterations %d interrupted %d)%n", |
143 getId(), getName(), iterations.get(), interrupted.get()); |
149 getId(), getName(), iterations.get(), interrupted.get()); |
144 try { |
150 try { |
145 stateChange(nextState); |
151 stateChange(nextState); |
146 lock.wait(); |
152 lock.wait(); |
147 System.out.format("%d: %s wakes up from waiting (interations %d interrupted %d)%n", |
153 log("%d: %s wakes up from waiting (iterations %d interrupted %d)%n", |
148 getId(), getName(), iterations.get(), interrupted.get()); |
154 getId(), getName(), iterations.get(), interrupted.get()); |
149 } catch (InterruptedException e) { |
155 } catch (InterruptedException e) { |
150 // ignore |
156 // ignore |
151 interrupted.incrementAndGet(); |
157 interrupted.incrementAndGet(); |
152 } |
158 } |
153 } |
159 } |
154 break; |
160 break; |
155 } |
161 } |
156 case S_TIMED_WAITING: { |
162 case S_TIMED_WAITING: { |
157 synchronized (lock) { |
163 synchronized (lock) { |
158 System.out.format("%d: %s is going to timed waiting (interations %d interrupted %d)%n", |
164 log("%d: %s is going to timed waiting (iterations %d interrupted %d)%n", |
159 getId(), getName(), iterations.get(), interrupted.get()); |
165 getId(), getName(), iterations.get(), interrupted.get()); |
160 try { |
166 try { |
161 stateChange(nextState); |
167 stateChange(nextState); |
162 lock.wait(10000); |
168 lock.wait(10000); |
163 System.out.format("%d: %s wakes up from timed waiting (interations %d interrupted %d)%n", |
169 log("%d: %s wakes up from timed waiting (iterations %d interrupted %d)%n", |
164 getId(), getName(), iterations.get(), interrupted.get()); |
170 getId(), getName(), iterations.get(), interrupted.get()); |
165 } catch (InterruptedException e) { |
171 } catch (InterruptedException e) { |
166 // ignore |
172 // ignore |
167 interrupted.incrementAndGet(); |
173 interrupted.incrementAndGet(); |
168 } |
174 } |
169 } |
175 } |
170 break; |
176 break; |
171 } |
177 } |
172 case S_PARKED: { |
178 case S_PARKED: { |
173 System.out.format("%d: %s is going to park (interations %d)%n", |
179 log("%d: %s is going to park (iterations %d)%n", |
174 getId(), getName(), iterations.get()); |
180 getId(), getName(), iterations.get()); |
175 stateChange(nextState); |
181 stateChange(nextState); |
176 LockSupport.park(); |
182 LockSupport.park(); |
177 break; |
183 break; |
178 } |
184 } |
179 case S_TIMED_PARKED: { |
185 case S_TIMED_PARKED: { |
180 System.out.format("%d: %s is going to timed park (interations %d)%n", |
186 log("%d: %s is going to timed park (iterations %d)%n", |
181 getId(), getName(), iterations.get()); |
187 getId(), getName(), iterations.get()); |
182 long deadline = System.currentTimeMillis() + 10000*1000; |
188 long deadline = System.currentTimeMillis() + 10000*1000; |
183 stateChange(nextState); |
189 stateChange(nextState); |
184 LockSupport.parkUntil(deadline); |
190 LockSupport.parkUntil(deadline); |
185 break; |
191 break; |
186 } |
192 } |
187 case S_SLEEPING: { |
193 case S_SLEEPING: { |
188 System.out.format("%d: %s is going to sleep (interations %d interrupted %d)%n", |
194 log("%d: %s is going to sleep (iterations %d interrupted %d)%n", |
189 getId(), getName(), iterations.get(), interrupted.get()); |
195 getId(), getName(), iterations.get(), interrupted.get()); |
190 try { |
196 try { |
191 stateChange(nextState); |
197 stateChange(nextState); |
192 Thread.sleep(1000000); |
198 Thread.sleep(1000000); |
193 } catch (InterruptedException e) { |
199 } catch (InterruptedException e) { |
194 // finish sleeping |
200 // finish sleeping |
268 nextState(timed ? S_TIMED_PARKED : S_PARKED); |
274 nextState(timed ? S_TIMED_PARKED : S_PARKED); |
269 } |
275 } |
270 |
276 |
271 private void nextState(int s) throws InterruptedException { |
277 private void nextState(int s) throws InterruptedException { |
272 final long id = Thread.currentThread().getId(); |
278 final long id = Thread.currentThread().getId(); |
273 System.out.format("%d: wait until the thread transitions to %s %s%n", |
279 log("%d: wait until the thread transitions to %s %s%n", |
274 id, toStateName(s), phaserToString(phaser)); |
280 id, toStateName(s), phaserToString(phaser)); |
275 this.newState = s; |
281 this.newState = s; |
276 int phase = phaser.arrive(); |
282 int phase = phaser.arrive(); |
277 System.out.format("%d: awaiting party arrive %s %s%n", |
283 log("%d: awaiting party arrive %s %s%n", |
278 id, toStateName(s), phaserToString(phaser)); |
284 id, toStateName(s), phaserToString(phaser)); |
279 for (;;) { |
285 for (;;) { |
280 // when this thread has changed its state before it waits or parks |
286 // when this thread has changed its state before it waits or parks |
281 // on a lock, a potential race might happen if it misses the notify |
287 // on a lock, a potential race might happen if it misses the notify |
282 // or unpark. Hence await for the phaser to advance with timeout |
288 // or unpark. Hence await for the phaser to advance with timeout |
283 // to cope with this race condition. |
289 // to cope with this race condition. |
299 default: |
305 default: |
300 break; |
306 break; |
301 } |
307 } |
302 try { |
308 try { |
303 phaser.awaitAdvanceInterruptibly(phase, 100, TimeUnit.MILLISECONDS); |
309 phaser.awaitAdvanceInterruptibly(phase, 100, TimeUnit.MILLISECONDS); |
304 System.out.format("%d: arrived at %s %s%n", |
310 log("%d: arrived at %s %s%n", |
305 id, toStateName(s), phaserToString(phaser)); |
311 id, toStateName(s), phaserToString(phaser)); |
306 return; |
312 return; |
307 } catch (TimeoutException ex) { |
313 } catch (TimeoutException ex) { |
308 // this thread hasn't arrived at this phase |
314 // this thread hasn't arrived at this phase |
309 System.out.format("%d: Timeout: %s%n", id, phaser); |
315 log("%d: Timeout: %s%n", id, phaser); |
310 } |
316 } |
311 } |
317 } |
312 } |
318 } |
|
319 |
313 private String phaserToString(Phaser p) { |
320 private String phaserToString(Phaser p) { |
314 return "[phase = " + p.getPhase() + |
321 return "[phase = " + p.getPhase() + |
315 " parties = " + p.getRegisteredParties() + |
322 " parties = " + p.getRegisteredParties() + |
316 " arrived = " + p.getArrivedParties() + "]"; |
323 " arrived = " + p.getArrivedParties() + "]"; |
317 } |
324 } |
|
325 |
318 private String toStateName(int state) { |
326 private String toStateName(int state) { |
319 switch (state) { |
327 switch (state) { |
320 case S_RUNNABLE: |
328 case S_RUNNABLE: |
321 return "runnable"; |
329 return "runnable"; |
322 case S_WAITING: |
330 case S_WAITING: |