ConstantTimeout.java
package de.uka.ipd.sdq.beagle.core.timeout;
import org.apache.commons.lang3.Validate;
/**
* Provides a constant timeout which cannot be changed.
*
* @author Christoph Michelbach
*/
public class ConstantTimeout extends ExecutionTimeBasedTimeout {
/**
* The timeout in milliseconds.
*/
private final long timeout;
/**
* Constructs a new constant timeout.
*
* @param timeout The timeout in milliseconds. Must not be negative.
*/
public ConstantTimeout(final int timeout) {
Validate.isTrue(timeout >= 0);
this.timeout = timeout;
}
@Override
public boolean isReached() {
Validate.isTrue(this.initialised);
return this.startingTime + this.timeout - System.currentTimeMillis() < 0;
}
/**
* Returns the timeout in milliseconds.
*
* @return The timeout in milliseconds.
*/
public long getTimeout() {
Validate.isTrue(this.initialised);
return this.timeout;
}
@Override
public void reportOneStepProgress() {
Validate.isTrue(this.initialised);
}
/**
* Calls the callback handlers once the timeout is reached.
*/
private void notifyOnReachedTimeout() {
long timeToSleep = this.startingTime + this.timeout - System.currentTimeMillis();
// Wait until the timeout is up.
while (!this.isReached()) {
assert timeToSleep >= 0;
try {
Thread.sleep(timeToSleep);
} catch (final InterruptedException exception) {
// Retry on interrupt. No handling is needed because the loop just
// tries again.
}
/**
* This has to be done at the end of the loop, not at the beginning. Otherwise
* the timeout can be reached right before the first instruction in the loop
* body but not in the loop header causing {@code timeToSleep} to become
* negative. This would be an illegal argument for {@link Thread#sleep(long)}.
*/
timeToSleep = this.startingTime + this.timeout - System.currentTimeMillis();
}
for (final Runnable callback : this.callbacks) {
new Thread(callback).start();
}
}
@Override
protected void implementationInit() {
new Thread(this::notifyOnReachedTimeout).start();
}
}