aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/java/com/jogamp/common/util/WorkerThread.java51
-rw-r--r--src/junit/com/jogamp/common/util/TestWorkerThread01.java30
2 files changed, 57 insertions, 24 deletions
diff --git a/src/java/com/jogamp/common/util/WorkerThread.java b/src/java/com/jogamp/common/util/WorkerThread.java
index 3cb36d9..a3a9914 100644
--- a/src/java/com/jogamp/common/util/WorkerThread.java
+++ b/src/java/com/jogamp/common/util/WorkerThread.java
@@ -29,6 +29,7 @@ package com.jogamp.common.util;
import java.time.Duration;
import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -51,7 +52,9 @@ public class WorkerThread {
private volatile boolean shallPause = true;
private volatile boolean shallStop = false;
private final Duration minPeriod;
- private final boolean useMinPeriod;
+ private final Duration minDelay;
+ private final long minDelayMS;
+ private final boolean useMinimum;
private final Callback cbWork;
private final Runnable cbInitLocked;
private final Runnable cbEndLocked;
@@ -62,24 +65,28 @@ public class WorkerThread {
/**
* Instantiates a new {@link WorkerThread}.
* @param minPeriod minimum work-loop-period to throttle execution or {@code null} if unthrottled, see {@link #getSleptDuration()}
+ * @param minDelay minimum work-loop-delay to throttle execution or {@code null} if unthrottled, see {@link #getSleptDuration()}
* @param daemonThread argument for {@link Thread#setDaemon(boolean)}
* @param work the actual work {@link Callback} to perform.
*/
- public WorkerThread(final Duration minPeriod, final boolean daemonThread, final Callback work) {
- this(minPeriod, daemonThread, work, null, null);
+ public WorkerThread(final Duration minPeriod, final Duration minDelay, final boolean daemonThread, final Callback work) {
+ this(minPeriod, minDelay, daemonThread, work, null, null);
}
/**
* Instantiates a new {@link WorkerThread}.
* @param minPeriod minimum work-loop-period to throttle execution or {@code null} if unthrottled, see {@link #getSleptDuration()}
+ * @param minDelay minimum work-loop-delay to throttle execution or {@code null} if unthrottled, see {@link #getSleptDuration()}
* @param daemonThread argument for {@link Thread#setDaemon(boolean)}
* @param work the actual work {@link Callback} to perform.
* @param init optional initialization {@link Runnable} called at {@link #start()} while locked
* @param end optional release {@link Runnable} called at {@link #stop()} while locked
*/
- public WorkerThread(final Duration minPeriod, final boolean daemonThread, final Callback work, final Runnable init, final Runnable end) {
+ public WorkerThread(final Duration minPeriod, final Duration minDelay, final boolean daemonThread, final Callback work, final Runnable init, final Runnable end) {
this.minPeriod = null != minPeriod ? minPeriod : Duration.ZERO;
- this.useMinPeriod = this.minPeriod.toMillis() > 0;
+ this.minDelay = null != minDelay ? minDelay : Duration.ZERO;
+ this.minDelayMS = minDelay.toMillis();
+ this.useMinimum = this.minPeriod.toMillis() > 0 || this.minDelayMS > 0;
this.cbWork = work;
this.cbInitLocked = init;
this.cbEndLocked = end;
@@ -205,9 +212,17 @@ public class WorkerThread {
public final Duration getMinPeriod() { return minPeriod; }
/**
- * Returns the slept {@link Duration} delta of {@link #getMinPeriod()} and consumed {@link Callback#run()} duration.
+ * Returns enforced minimum work-loop-delay or {@link Duration#ZERO} for none.
+ * @see #getSleptDuration()
+ */
+ public final Duration getMinDelay() { return minDelay; }
+
+ /**
+ * Returns the slept {@link Duration} delta of {@link #getMinPeriod()} and consumed {@link Callback#run()} duration,
+ * which minimum is {@link #getMinDelay()}.
* <p>
- * Returns {@link Duration#ZERO zero} for {@link Duration#ZERO zero} {@link #getMinPeriod()} or exceeding {@link Callback#run()} duration.
+ * Returns {@link Duration#ZERO zero} for {@link Duration#ZERO zero} {@link #getMinPeriod()} and {@link #getMinDelay()} or exceeding {@link Callback#run()} duration
+ * without {@link #getMinDelay()}.
* </p>
*/
public final Duration getSleptDuration() { return sleptDuration; }
@@ -217,7 +232,7 @@ public class WorkerThread {
synchronized(this) {
return "Worker[running "+isRunning+", active "+isActive+", blocked "+isBlocked+
", shall[pause "+shallPause+", stop "+shallStop+
- "], minPeriod[set "+minPeriod.toMillis()+"ms, sleptDelta "+sleptDuration.toMillis()+
+ "], minDelay "+minDelay.toMillis()+"ms, minPeriod[set "+minPeriod.toMillis()+"ms, sleptDelta "+sleptDuration.toMillis()+
"ms], daemon "+isDaemonThread+", thread "+thread+"]";
}
}
@@ -263,19 +278,26 @@ public class WorkerThread {
cbWork.run();
}
isBlocked = false;
- if( useMinPeriod ) {
+ if( useMinimum ) {
final Instant t1 = Instant.now();
final Duration td = Duration.between(t0, t1);
if( minPeriod.compareTo(td) > 0 ) {
- final Duration sleepMinPeriodDelta = minPeriod.minus(td);
- final long tdMinMS = sleepMinPeriodDelta.toMillis();
- if( tdMinMS > 0 ) {
- sleptDuration = sleepMinPeriodDelta;
- java.lang.Thread.sleep( tdMinMS );
+ final Duration minPeriodDelta = minPeriod.minus(td);
+ final long minPeriodDeltaMS = minPeriodDelta.toMillis();
+ if( minPeriodDeltaMS > 0 ) {
+ final long minSleepMS = Math.max(minDelayMS, minPeriodDeltaMS);
+ sleptDuration = Duration.of(minSleepMS, ChronoUnit.MILLIS);
+ java.lang.Thread.sleep( minSleepMS );
+ } else if( minDelayMS > 0 ) {
+ sleptDuration = minDelay;
+ java.lang.Thread.sleep( minDelayMS );
} else {
sleptDuration = Duration.ZERO;
}
// java.util.concurrent.locks.LockSupport.parkNanos(tdMin.toNanos());
+ } else if( minDelayMS > 0 ) {
+ sleptDuration = minDelay;
+ java.lang.Thread.sleep( minDelayMS );
} else {
sleptDuration = Duration.ZERO;
}
@@ -311,5 +333,4 @@ public class WorkerThread {
WorkerThread.this.notifyAll(); // wake-up doStop()
}
} };
-
}
diff --git a/src/junit/com/jogamp/common/util/TestWorkerThread01.java b/src/junit/com/jogamp/common/util/TestWorkerThread01.java
index 9ac7d75..afd41a1 100644
--- a/src/junit/com/jogamp/common/util/TestWorkerThread01.java
+++ b/src/junit/com/jogamp/common/util/TestWorkerThread01.java
@@ -98,10 +98,11 @@ public class TestWorkerThread01 extends SingletonJunitCase {
System.err.println("WT Resume.X: "+wt);
}
- public void testAction(final long periodMS, final long actionMS) throws IOException, InterruptedException, InvocationTargetException {
+ public void testAction(final long periodMS, final long minDelayMS, final long actionMS) throws IOException, InterruptedException, InvocationTargetException {
final Action action = new Action( 0 < actionMS ? Duration.of(actionMS, ChronoUnit.MILLIS) : Duration.ZERO);
- final WorkerThread wt =new WorkerThread(Duration.of(periodMS, ChronoUnit.MILLIS), true /* daemonThread */, action);
- final long maxPeriodMS = Math.max(periodMS, actionMS);
+ final WorkerThread wt =new WorkerThread(Duration.of(periodMS, ChronoUnit.MILLIS),
+ Duration.of(minDelayMS, ChronoUnit.MILLIS), true /* daemonThread */, action);
+ final long maxPeriodMS = Math.max(minDelayMS+actionMS, Math.max(periodMS, actionMS));
int counterA = action.counter.get();
checkStopped(wt);
start(wt);
@@ -110,9 +111,10 @@ public class TestWorkerThread01 extends SingletonJunitCase {
{
final Duration td = action.td;
final Duration wt_slept = wt.getSleptDuration();
+ final long minEps = 4;
final long actionMS_d = td.minus( wt_slept ).toMillis() - actionMS;
- System.err.println("actionMS_d "+actionMS_d+" = td "+td.toMillis()+"ms - wt_slept "+wt_slept.toMillis()+"ms - actionMS "+actionMS+"ms");
- Assert.assertTrue(Math.abs(actionMS_d) < 4);
+ System.err.println("actionMS_d "+actionMS_d+" = td "+td.toMillis()+"ms - wt_slept "+wt_slept.toMillis()+"ms - actionMS "+actionMS+"ms < minEps "+minEps+"ms");
+ Assert.assertTrue(Math.abs(actionMS_d) < minEps);
}
checkStarted(wt, false /* isPaused */);
@@ -149,22 +151,32 @@ public class TestWorkerThread01 extends SingletonJunitCase {
@Test
public void test01ZeroAction() throws IOException, InterruptedException, InvocationTargetException {
- testAction(16 /* periodMS */, 0 /* actionMS*/);
+ testAction(16 /* periodMS */, 0 /* minDelayMS */, 0 /* actionMS*/);
}
@Test
public void test02MidAction() throws IOException, InterruptedException, InvocationTargetException {
- testAction(16 /* periodMS */, 8 /* actionMS*/);
+ testAction(16 /* periodMS */, 0 /* minDelayMS */, 8 /* actionMS*/);
}
@Test
public void test03HeavyAction() throws IOException, InterruptedException, InvocationTargetException {
- testAction(16 /* periodMS */, 20 /* actionMS*/);
+ testAction(16 /* periodMS */, 0 /* minDelayMS */, 20 /* actionMS*/);
}
@Test
public void test03ZeroMidAction() throws IOException, InterruptedException, InvocationTargetException {
- testAction(0 /* periodMS */, 8 /* actionMS*/);
+ testAction(0 /* periodMS */, 0 /* minDelayMS */, 8 /* actionMS*/);
+ }
+
+ @Test
+ public void test04ZeroMinDelayMidAction() throws IOException, InterruptedException, InvocationTargetException {
+ testAction(0 /* periodMS */, 4 /* minDelayMS */, 8 /* actionMS*/);
+ }
+
+ @Test
+ public void test05MinDelayMidAction() throws IOException, InterruptedException, InvocationTargetException {
+ testAction(8 /* periodMS */, 8 /* minDelayMS */, 8 /* actionMS*/);
}
public static void main(final String args[]) throws IOException {