CloseableStopwatch.java
// Generated by delombok at Mon Nov 18 07:27:48 UTC 2024
package de.larssh.utils.time;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import de.larssh.utils.CompletedException;
/**
* Abstract and synchronized implementation of a closeable {@link Stopwatch}.
* Once a {@code CloseableStopwatch} is closed no more checkpoints can be
* created and {@link #sinceStart()} and {@link #sinceLast()} return durations
* based on the stopwatches stopping time.
*
* <p>
* Extending class are meant to be used inside try-with-resource blocks.
*
* <p>
* {@link #close()} can be called multiple times while all but the first call
* are ignored.
*/
public abstract class CloseableStopwatch extends Stopwatch implements AutoCloseable {
/**
* Instant at the stopwatches stopping or empty if the stopwatch is not stopped,
* yet.
*/
private volatile Optional<Instant> stopInstant = Optional.empty();
/**
* Object used for locking
*/
private final Object lock = new Object();
/**
* Abstract and synchronized implementation of a closeable {@link Stopwatch}.
* Once a {@code CloseableStopwatch} is closed no more checkpoints can be
* created and {@link #sinceStart()} and {@link #sinceLast()} return durations
* based on the stopwatches stopping time.
*
* <p>
* Extending class are meant to be used inside try-with-resource blocks.
*
* <p>
* {@link #close()} can be called multiple times while all but the first call
* are ignored.
*/
public CloseableStopwatch() {
// no fields to be initialized
}
/**
* {@inheritDoc}
*
* @throws CompletedException Once the {@link CloseableStopwatch} is closed no
* more checkpoints can be added.
*/
@Override
public Checkpoint checkpoint(final String name) {
synchronized (lock) {
if (isStopped()) {
throw new CompletedException();
}
return super.checkpoint(name);
}
}
/**
* {@inheritDoc}
*/
@Override
public void close() {
synchronized (lock) {
if (!isStopped()) {
stopInstant = Optional.of(Instant.now());
}
}
}
/**
* Returns {@code true} if the stopwatch is stopped.
*
* @return {@code true} if the stopwatch is stopped
*/
public boolean isStopped() {
return stopInstant.isPresent();
}
/**
* {@inheritDoc}
*/
@Override
public Duration sinceLast() {
return Duration.between(getLastInstant(), getStopInstant().orElseGet(Instant::now));
}
/**
* {@inheritDoc}
*/
@Override
public Duration sinceStart() {
return Duration.between(getStartInstant(), getStopInstant().orElseGet(Instant::now));
}
/**
* Instant at the stopwatches stopping or empty if the stopwatch is not stopped,
* yet.
*
* @return the instant at the stopwatches stopping or empty
*/
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public Optional<Instant> getStopInstant() {
return this.stopInstant;
}
@edu.umd.cs.findbugs.annotations.NonNull
@java.lang.Override
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public java.lang.String toString() {
return "CloseableStopwatch(super=" + super.toString() + ", stopInstant=" + this.getStopInstant() + ")";
}
}