29package com.jogamp.common.util;
31import java.io.IOException;
32import java.lang.reflect.InvocationTargetException;
33import java.time.Duration;
34import java.time.Instant;
35import java.time.temporal.ChronoUnit;
36import java.util.concurrent.atomic.AtomicInteger;
38import org.junit.Assert;
41import com.jogamp.junit.util.SingletonJunitCase;
43import jogamp.common.os.PlatformPropsImpl;
45import org.junit.FixMethodOrder;
46import org.junit.runners.MethodSorters;
48@FixMethodOrder(MethodSorters.NAME_ASCENDING)
53 final AtomicInteger counter =
new AtomicInteger(0);
54 Instant tlast = Instant.now();
55 volatile Duration td = Duration.ZERO;
57 Action(
final Duration sleep) {
62 public void run(
final WorkerThread self)
throws InterruptedException {
64 java.lang.Thread.sleep(sleep.toMillis());
67 final Instant t1 = Instant.now();
68 td = Duration.between(tlast, t1);
69 final int v = counter.incrementAndGet();
74 static class StateCB
implements WorkerThread.StateCallback {
75 final AtomicInteger initCounter =
new AtomicInteger(0);
76 final AtomicInteger pausedCounter =
new AtomicInteger(0);
77 final AtomicInteger resumedCounter =
new AtomicInteger(0);
78 final AtomicInteger endCounter =
new AtomicInteger(0);
81 public void run(
final WorkerThread self,
final State cause)
throws InterruptedException {
85 endCounter.incrementAndGet();
88 initCounter.incrementAndGet();
91 pausedCounter.incrementAndGet();
94 resumedCounter.incrementAndGet();
102 static void checkStarted(
final WorkerThread wt,
final boolean isPaused) {
104 Assert.assertEquals(
"isPaused "+isPaused+
", "+wt.
toString(), !isPaused, wt.
isActive());
112 static void start(
final WorkerThread wt,
final boolean paused) {
117 static void stop(
final WorkerThread wt,
final boolean wait) {
122 static void pause(
final WorkerThread wt,
final boolean wait) {
133 public void testAction(
final boolean startPaused,
final long periodMS,
final long minDelayMS,
final long actionMS)
throws IOException, InterruptedException, InvocationTargetException {
136 final long toleranceMS = PlatformPropsImpl.JAVA_21 ? 20 : 4;
137 final Action action =
new Action( 0 < actionMS ? Duration.of(actionMS, ChronoUnit.MILLIS) : Duration.ZERO);
138 final StateCB stateCB =
new StateCB();
140 Duration.of(minDelayMS, ChronoUnit.MILLIS),
true , action, stateCB);
142 final long maxPeriodMS = Math.max(minDelayMS+actionMS, Math.max(periodMS, actionMS));
143 System.err.println(
"testAction: startPaused "+startPaused+
", maxPeriodMS "+maxPeriodMS+
", actionMS "+actionMS+
", "+wt);
145 int counterA = action.counter.get();
147 Assert.assertEquals(0, stateCB.initCounter.get());
148 Assert.assertEquals(0, action.counter.get());
149 Assert.assertEquals(0, stateCB.pausedCounter.get());
150 Assert.assertEquals(0, stateCB.resumedCounter.get());
151 Assert.assertEquals(0, stateCB.endCounter.get());
152 start(wt, startPaused);
153 checkStarted(wt, startPaused );
154 Assert.assertEquals(1, stateCB.initCounter.get());
155 Assert.assertEquals(startPaused?1:0, stateCB.pausedCounter.get());
156 Assert.assertEquals(startPaused?0:0, stateCB.resumedCounter.get());
157 Assert.assertEquals(0, stateCB.endCounter.get());
160 checkStarted(wt,
false );
161 Assert.assertEquals(1, stateCB.initCounter.get());
162 Assert.assertEquals(1, stateCB.pausedCounter.get());
163 Assert.assertEquals(1, stateCB.resumedCounter.get());
164 Assert.assertEquals(0, stateCB.endCounter.get());
166 Thread.sleep(maxPeriodMS*3);
168 final Duration td = action.td;
170 final long actionMS_d = td.minus( wt_slept ).toMillis() - actionMS;
171 System.err.println(
"actionMS_d "+actionMS_d+
" = td "+td.toMillis()+
"ms - wt_slept "+wt_slept.toMillis()+
"ms - actionMS "+actionMS+
"ms < toleranceMS "+toleranceMS+
"ms");
172 Assert.assertTrue(Math.abs(actionMS_d) < toleranceMS);
175 checkStarted(wt,
false );
178 Assert.assertEquals(1, stateCB.initCounter.get());
179 Assert.assertEquals(startPaused?1:0, stateCB.pausedCounter.get());
180 Assert.assertEquals(startPaused?1:0, stateCB.resumedCounter.get());
181 Assert.assertEquals(1, stateCB.endCounter.get());
182 int counterB = action.counter.get();
183 Assert.assertTrue(counterB > counterA);
185 counterA = action.counter.get();
187 start(wt, startPaused);
188 checkStarted(wt, startPaused );
189 Assert.assertEquals(2, stateCB.initCounter.get());
190 Assert.assertEquals(startPaused?2:0, stateCB.pausedCounter.get());
191 Assert.assertEquals(startPaused?1:0, stateCB.resumedCounter.get());
192 Assert.assertEquals(1, stateCB.endCounter.get());
195 checkStarted(wt,
false );
196 Assert.assertEquals(2, stateCB.initCounter.get());
197 Assert.assertEquals(startPaused?2:0, stateCB.pausedCounter.get());
198 Assert.assertEquals(startPaused?2:0, stateCB.resumedCounter.get());
199 Assert.assertEquals(1, stateCB.endCounter.get());
201 Thread.sleep(maxPeriodMS*3);
203 checkStarted(wt,
false );
205 checkStarted(wt,
true );
206 Assert.assertEquals(2, stateCB.initCounter.get());
207 Assert.assertEquals(startPaused?3:1, stateCB.pausedCounter.get());
208 Assert.assertEquals(startPaused?2:0, stateCB.resumedCounter.get());
209 Assert.assertEquals(1, stateCB.endCounter.get());
210 counterB = action.counter.get();
211 Assert.assertTrue(counterB > counterA);
213 Thread.sleep(maxPeriodMS);
214 counterA = action.counter.get();
215 Assert.assertTrue(counterB == counterA);
217 checkStarted(wt,
false );
218 Assert.assertEquals(2, stateCB.initCounter.get());
219 Assert.assertEquals(startPaused?3:1, stateCB.pausedCounter.get());
220 Assert.assertEquals(startPaused?3:1, stateCB.resumedCounter.get());
221 Assert.assertEquals(1, stateCB.endCounter.get());
222 Thread.sleep(maxPeriodMS*3);
224 checkStarted(wt,
false );
226 checkStarted(wt,
true );
227 Assert.assertEquals(2, stateCB.initCounter.get());
228 Assert.assertEquals(startPaused?4:2, stateCB.pausedCounter.get());
229 Assert.assertEquals(startPaused?3:1, stateCB.resumedCounter.get());
230 Assert.assertEquals(1, stateCB.endCounter.get());
231 counterB = action.counter.get();
232 Assert.assertTrue(counterB > counterA);
235 checkStarted(wt,
true );
238 Assert.assertEquals(2, stateCB.initCounter.get());
239 Assert.assertEquals(startPaused?4:2, stateCB.pausedCounter.get());
240 Assert.assertEquals(startPaused?4:2, stateCB.resumedCounter.get());
241 Assert.assertEquals(2, stateCB.endCounter.get());
242 counterB = action.counter.get();
243 Assert.assertTrue(counterB == counterA);
247 Assert.assertEquals(2, stateCB.initCounter.get());
248 Assert.assertEquals(startPaused?4:2, stateCB.pausedCounter.get());
249 Assert.assertEquals(startPaused?4:2, stateCB.resumedCounter.get());
250 Assert.assertEquals(2, stateCB.endCounter.get());
254 Assert.assertEquals(2, stateCB.initCounter.get());
255 Assert.assertEquals(startPaused?4:2, stateCB.pausedCounter.get());
256 Assert.assertEquals(startPaused?4:2, stateCB.resumedCounter.get());
257 Assert.assertEquals(2, stateCB.endCounter.get());
261 public void test01ZeroAction() throws IOException, InterruptedException, InvocationTargetException {
262 testAction(
false, 16 , 0 , 0 );
263 testAction(
true, 16 , 0 , 0 );
267 public void test02MidAction() throws IOException, InterruptedException, InvocationTargetException {
268 testAction(
false, 16 , 0 , 8 );
269 testAction(
true, 16 , 0 , 8 );
273 public void test03HeavyAction() throws IOException, InterruptedException, InvocationTargetException {
274 testAction(
false, 16 , 0 , 20 );
275 testAction(
true, 16 , 0 , 20 );
280 testAction(
false, 0 , 0 , 8 );
281 testAction(
true, 0 , 0 , 8 );
286 testAction(
false, 0 , 4 , 8 );
287 testAction(
true, 0 , 4 , 8 );
292 testAction(
false, 8 , 8 , 8 );
293 testAction(
true, 8 , 8 , 8 );
297 public void test10InitEnd01() throws IOException, InterruptedException, InvocationTargetException {
299 final AtomicInteger actionLatch =
new AtomicInteger(0);
300 final WorkerThread.Callback action = (
final WorkerThread self) -> {
301 java.lang.Thread.sleep(1);
302 final boolean v = actionLatch.compareAndSet(0, 1);
305 final StateCB stateCB =
new StateCB();
307 Assert.assertEquals(0, stateCB.initCounter.get());
308 Assert.assertEquals(0, actionLatch.get());
309 Assert.assertEquals(0, stateCB.pausedCounter.get());
310 Assert.assertEquals(0, stateCB.resumedCounter.get());
311 Assert.assertEquals(0, stateCB.endCounter.get());
313 final long minPeriodMS = 2;
314 final long maxPeriodMS = 4;
316 Duration.of(0, ChronoUnit.MILLIS),
true ,
318 Assert.assertEquals(0, stateCB.initCounter.get());
319 Assert.assertEquals(0, actionLatch.get());
320 Assert.assertEquals(0, stateCB.pausedCounter.get());
321 Assert.assertEquals(0, stateCB.resumedCounter.get());
322 Assert.assertEquals(0, stateCB.endCounter.get());
326 checkStarted(wt,
true );
327 Assert.assertEquals(1, stateCB.initCounter.get());
328 Assert.assertEquals(0, actionLatch.get());
329 Assert.assertEquals(1, stateCB.pausedCounter.get());
330 Assert.assertEquals(0, stateCB.resumedCounter.get());
331 Assert.assertEquals(0, stateCB.endCounter.get());
334 checkStarted(wt,
false );
335 Assert.assertEquals(1, stateCB.initCounter.get());
337 Assert.assertEquals(1, stateCB.pausedCounter.get());
338 Assert.assertEquals(1, stateCB.resumedCounter.get());
339 Assert.assertEquals(0, stateCB.endCounter.get());
341 Thread.sleep(maxPeriodMS);
342 Assert.assertEquals(1, stateCB.initCounter.get());
343 Assert.assertEquals(1, actionLatch.get());
344 Assert.assertEquals(1, stateCB.pausedCounter.get());
345 Assert.assertEquals(1, stateCB.resumedCounter.get());
346 Assert.assertEquals(0, stateCB.endCounter.get());
348 checkStarted(wt,
false );
351 Assert.assertEquals(1, stateCB.initCounter.get());
352 Assert.assertEquals(1, actionLatch.get());
353 Assert.assertEquals(1, stateCB.pausedCounter.get());
354 Assert.assertEquals(1, stateCB.resumedCounter.get());
355 Assert.assertEquals(1, stateCB.endCounter.get());
358 Assert.assertEquals(0, actionLatch.get());
360 checkStarted(wt,
false);
361 Assert.assertEquals(2, stateCB.initCounter.get());
363 Assert.assertEquals(1, stateCB.pausedCounter.get());
364 Assert.assertEquals(1, stateCB.resumedCounter.get());
365 Assert.assertEquals(1, stateCB.endCounter.get());
367 Thread.sleep(maxPeriodMS);
368 Assert.assertEquals(2, stateCB.initCounter.get());
369 Assert.assertEquals(1, actionLatch.get());
370 Assert.assertEquals(1, stateCB.pausedCounter.get());
371 Assert.assertEquals(1, stateCB.resumedCounter.get());
372 Assert.assertEquals(1, stateCB.endCounter.get());
374 checkStarted(wt,
false );
377 Assert.assertEquals(2, stateCB.initCounter.get());
378 Assert.assertEquals(1, actionLatch.get());
379 Assert.assertEquals(1, stateCB.pausedCounter.get());
380 Assert.assertEquals(1, stateCB.resumedCounter.get());
381 Assert.assertEquals(2, stateCB.endCounter.get());
385 public void test11InitEnd02() throws IOException, InterruptedException, InvocationTargetException {
387 final AtomicInteger actionCounter =
new AtomicInteger(0);
388 final WorkerThread.Callback action = (
final WorkerThread self) -> {
389 java.lang.Thread.sleep(1);
390 final int v = actionCounter.incrementAndGet();
396 final StateCB stateCB =
new StateCB();
398 Assert.assertEquals(0, stateCB.initCounter.get());
399 Assert.assertEquals(0, actionCounter.get());
400 Assert.assertEquals(0, stateCB.pausedCounter.get());
401 Assert.assertEquals(0, stateCB.resumedCounter.get());
402 Assert.assertEquals(0, stateCB.endCounter.get());
406 final long minPeriodMS = 2;
407 final long maxPeriodMS = PlatformPropsImpl.JAVA_21 ? 40 : 16;
410 Duration.of(0, ChronoUnit.MILLIS),
true ,
412 Assert.assertEquals(0, stateCB.initCounter.get());
413 Assert.assertEquals(0, actionCounter.get());
414 Assert.assertEquals(0, stateCB.pausedCounter.get());
415 Assert.assertEquals(0, stateCB.resumedCounter.get());
416 Assert.assertEquals(0, stateCB.endCounter.get());
420 checkStarted(wt,
true );
421 Assert.assertEquals(1, stateCB.initCounter.get());
422 Assert.assertEquals(0, actionCounter.get());
423 Assert.assertEquals(1, stateCB.pausedCounter.get());
424 Assert.assertEquals(0, stateCB.resumedCounter.get());
425 Assert.assertEquals(0, stateCB.endCounter.get());
428 checkStarted(wt,
false );
429 Assert.assertEquals(1, stateCB.initCounter.get());
431 Assert.assertEquals(1, stateCB.pausedCounter.get());
432 Assert.assertEquals(1, stateCB.resumedCounter.get());
433 Assert.assertEquals(0, stateCB.endCounter.get());
435 Thread.sleep(maxPeriodMS);
436 Assert.assertEquals(1, stateCB.initCounter.get());
437 Assert.assertTrue(0 < actionCounter.get());
438 Assert.assertEquals(1, stateCB.pausedCounter.get());
439 Assert.assertEquals(1, stateCB.resumedCounter.get());
440 Assert.assertEquals(1, stateCB.endCounter.get());
443 actionCounter.set(0);
444 Assert.assertEquals(0, actionCounter.get());
446 checkStarted(wt,
false);
447 Assert.assertEquals(2, stateCB.initCounter.get());
449 Assert.assertEquals(1, stateCB.pausedCounter.get());
450 Assert.assertEquals(1, stateCB.resumedCounter.get());
451 Assert.assertEquals(1, stateCB.endCounter.get());
453 Thread.sleep(maxPeriodMS);
454 Assert.assertEquals(2, stateCB.initCounter.get());
455 Assert.assertTrue(0 < actionCounter.get());
456 Assert.assertEquals(1, stateCB.pausedCounter.get());
457 Assert.assertEquals(1, stateCB.resumedCounter.get());
458 Assert.assertEquals(2, stateCB.endCounter.get());
464 final AtomicInteger actionCounter =
new AtomicInteger(0);
465 final WorkerThread.Callback action = (
final WorkerThread self) -> {
466 java.lang.Thread.sleep(1);
467 final int v = actionCounter.incrementAndGet();
470 throw new RuntimeException(
"Test exception from worker action: "+
self);
473 final StateCB stateCB =
new StateCB();
475 Assert.assertEquals(0, stateCB.initCounter.get());
476 Assert.assertEquals(0, actionCounter.get());
477 Assert.assertEquals(0, stateCB.pausedCounter.get());
478 Assert.assertEquals(0, stateCB.resumedCounter.get());
479 Assert.assertEquals(0, stateCB.endCounter.get());
483 final long minPeriodMS = 2;
484 final long maxPeriodMS = PlatformPropsImpl.JAVA_21 ? 40 : 16;
487 Duration.of(0, ChronoUnit.MILLIS),
true ,
489 Assert.assertEquals(0, stateCB.initCounter.get());
490 Assert.assertEquals(0, actionCounter.get());
491 Assert.assertEquals(0, stateCB.pausedCounter.get());
492 Assert.assertEquals(0, stateCB.resumedCounter.get());
493 Assert.assertEquals(0, stateCB.endCounter.get());
497 checkStarted(wt,
true );
498 Assert.assertEquals(1, stateCB.initCounter.get());
499 Assert.assertEquals(0, actionCounter.get());
500 Assert.assertEquals(1, stateCB.pausedCounter.get());
501 Assert.assertEquals(0, stateCB.resumedCounter.get());
502 Assert.assertEquals(0, stateCB.endCounter.get());
505 checkStarted(wt,
false );
506 Assert.assertEquals(1, stateCB.initCounter.get());
508 Assert.assertEquals(1, stateCB.pausedCounter.get());
509 Assert.assertEquals(1, stateCB.resumedCounter.get());
510 Assert.assertEquals(0, stateCB.endCounter.get());
512 Thread.sleep(maxPeriodMS);
513 Assert.assertEquals(1, stateCB.initCounter.get());
514 Assert.assertTrue(0 < actionCounter.get());
515 Assert.assertEquals(2, stateCB.pausedCounter.get());
516 Assert.assertEquals(1, stateCB.resumedCounter.get());
517 Assert.assertEquals(0, stateCB.endCounter.get());
518 checkStarted(wt,
true );
520 Assert.assertNotNull(wt.
getError(
true));
521 final int counterA = actionCounter.get();
524 checkStarted(wt,
false );
525 Assert.assertEquals(1, stateCB.initCounter.get());
526 Assert.assertTrue(0 < actionCounter.get());
527 Assert.assertEquals(2, stateCB.pausedCounter.get());
528 Assert.assertEquals(2, stateCB.resumedCounter.get());
529 Assert.assertEquals(0, stateCB.endCounter.get());
530 Thread.sleep(maxPeriodMS);
534 final int counterB = actionCounter.get();
535 Assert.assertTrue(counterB > counterA);
536 Assert.assertEquals(1, stateCB.initCounter.get());
537 Assert.assertTrue(0 < actionCounter.get());
538 Assert.assertEquals(2, stateCB.pausedCounter.get());
539 Assert.assertEquals(2, stateCB.resumedCounter.get());
540 Assert.assertEquals(1, stateCB.endCounter.get());
543 public static void main(
final String args[])
throws IOException {
545 org.junit.runner.JUnitCore.
main(tstname);
void test03ZeroMidAction()
void testAction(final boolean startPaused, final long periodMS, final long minDelayMS, final long actionMS)
void test04ZeroMinDelayMidAction()
void test05MinDelayMidAction()
static void main(final String args[])
void test20ExceptionAtWork()
A re-start()'able, pause(boolean)'able and interrupt'able worker thread with an optional minimum exec...
final boolean hasError()
Returns true if an exception occured during Callable work execution.
final synchronized void start(final boolean paused)
Starts execution of a new worker thread if not isRunning, i.e.
final Exception getError(final boolean clear)
Returns the exception is hasError().
final synchronized void pause(final boolean waitUntilDone)
Pauses execution of the start()'ed worker thread.
final synchronized void resume()
Resumes execution of the pause(boolean)'ed worker thread.
final synchronized void stop(final boolean waitUntilDone)
Stops execution of the start()'ed worker thread.
final Thread getThread()
Returns the worker thread if isRunning(), otherwise null.
final boolean isRunning()
Returns true if the worker thread has started via start() and has not ended, e.g.
final Duration getSleptDuration()
Returns the slept Duration delta of getMinPeriod() and consumed Callback#run() duration,...
final boolean isActive()
Returns true if the worker thread isRunning() and is not paused.