All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.larssh.utils.time.Stopwatch Maven / Gradle / Ivy

// Generated by delombok at Tue Jan 28 00:13:20 CET 2020
package de.larssh.utils.time;

import static de.larssh.utils.function.ThrowingConsumer.throwing;
import static java.util.Collections.synchronizedList;
import static java.util.Collections.unmodifiableList;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Stream;
import de.larssh.utils.Nullables;
import edu.umd.cs.findbugs.annotations.Nullable;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

/**
 * Implementation of a synchronized stopwatch starting at {@link Instant#now()}.
 * {@link #sinceStart()} can be used to retrieve the duration since the
 * stopwatch started.
 *
 * 

* {@link #checkpoint(String)} adds a new checkpoint. It might be used for split * or lap times. {@link #sinceLast()} can be used to retrieve the duration since * the last checkpoint was created. */ public class Stopwatch { /** * List of checkpoints */ private final List checkpoints = synchronizedList(new LinkedList<>()); /** * Instant at the stopwatches start */ private final Instant startInstant = Instant.now(); /** * Object used for locking */ private final Object lock = new Object(); /** * Adds a new checkpoint referenced by {@code name}. * *

* {@code name} does not need to be unique. Multiple checkpoints with the same * name might exist. * * @param name name to reference the checkpoint * @return the new checkpoint */ public Checkpoint checkpoint(final String name) { synchronized (lock) { final Checkpoint checkpoint = new Checkpoint(this, name, Instant.now(), getLastCheckpoint()); checkpoints.add(checkpoint); return checkpoint; } } /** * List of checkpoints * * @return the list of checkpoints */ public List getCheckpoints() { return unmodifiableList(checkpoints); } /** * The last created {@link Checkpoint} or empty if no checkpoint was created * * @return the last created checkpoint */ public Optional getLastCheckpoint() { return checkpoints.isEmpty() ? Optional.empty() : Optional.of(checkpoints.get(checkpoints.size() - 1)); } /** * Instant of the last created {@link Checkpoint} or the stopwatches starting * time if no checkpoint was created * * @return the last created instant or the stopwatches starting time */ public Instant getLastInstant() { return checkpoints.isEmpty() ? getStartInstant() : checkpoints.get(checkpoints.size() - 1).getInstant(); } /** * Duration since the last created {@link Checkpoint} or the stopwatches * starting time if no checkpoint was created * * @return the duration since last checkpoints instant or the stopwatches * starting time */ public Duration sinceLast() { return Duration.between(getLastInstant(), Instant.now()); } /** * Duration since the stopwatches start * * @return the duration since the stopwatches start */ public Duration sinceStart() { return Duration.between(getStartInstant(), Instant.now()); } /** * Waits for {@code duration} using {@code Thread#sleep(long)}. If reached, it * times out at {@code timeoutSinceStart} after the {@link Stopwatch} start. * * @param duration duration to wait * @param timeoutSinceStart timeout duration since the {@link Stopwatch} start * @return {@code true} if the timeout was not reached and {@code false} if the * timeout has been reached * @throws InterruptedException if any thread has interrupted the current thread */ @SuppressWarnings("unused") @SuppressFBWarnings(value = "MDM_THREAD_YIELD", justification = "This is really intended to sleep for a specified duration.") public boolean waitFor(final Duration duration, final Duration timeoutSinceStart) throws InterruptedException { return waitFor(duration, timeoutSinceStart, throwing(waiting -> Thread.sleep(Nullables.orElseThrow(waiting).toMillis()))); } /** * Waits for {@code duration} using {@code wait}. If reached, it times out at * {@code timeoutSinceStart} after the {@link Stopwatch} start. * *

* Note: The {@link Duration} given to {@code wait} might be less than * {@code duration} to handle {@code timeoutSinceStart} more precisely. * * @param duration duration to wait * @param timeoutSinceStart timeout duration since the {@link Stopwatch} start * @param wait method to use for waiting * @return {@code true} if the timeout was not reached and {@code false} if the * timeout has been reached */ @SuppressFBWarnings(value = "PRMC_POSSIBLY_REDUNDANT_METHOD_CALLS", justification = "no redundant calls, because Instant.now() might return different values") public boolean waitFor(final Duration duration, final Duration timeoutSinceStart, final Consumer wait) { if (duration.isNegative()) { throw new IllegalArgumentException(String.format("Parameter \"duration\" must not be negative, but is %s.", duration)); } if (timeoutSinceStart.isNegative()) { throw new IllegalArgumentException(String.format("Parameter \"timeoutSinceStart\" must not be negative, but is %s.", timeoutSinceStart)); } final Instant timeout = getStartInstant().plus(timeoutSinceStart); final Duration maxWaiting = Duration.between(Instant.now(), timeout); final Duration actualWaiting = maxWaiting.compareTo(duration) > 0 ? duration : maxWaiting; if (!actualWaiting.isNegative() && !actualWaiting.isZero()) { wait.accept(actualWaiting); } return !Instant.now().isAfter(timeout); } /** * Sequential {@code Stream} with the checkpoints as its source * * @return a sequential {@code Stream} over the checkpoints */ public Stream stream() { return checkpoints.stream(); } /** * Implementation of a stopwatches checkpoint. It might be used for split or lap * times. */ public static class Checkpoint implements Comparable, TemporalAccessor { /** * Comparator of {@link Checkpoint} */ private static final Comparator COMPARATOR = Comparator.comparing(Checkpoint::getInstant).thenComparing(Comparator.comparing(checkpoint -> checkpoint.getPreviousCheckpoint().map(Checkpoint::getInstant).orElse(Instant.MIN))); /** * Stopwatch * * @return the stopwatch */ private final Stopwatch stopwatch; /** * Checkpoints name as reference * * @return the checkpoints name */ private final String name; /** * Instant * * @return the instant */ private final Instant instant; /** * Previous checkpoint or empty if this is the stopwatches first checkpoint * * @return the previous checkpoint */ private final Optional previousCheckpoint; /** {@inheritDoc} */ @Override public int compareTo(@Nullable final Checkpoint object) { return Objects.compare(this, object, COMPARATOR); } /** {@inheritDoc} */ @Override public long getLong(@Nullable final TemporalField field) { return getInstant().getLong(field); } /** * Instant of the previous {@link Checkpoint} or the stopwatches starting time * if this is the first checkpoint * * @return the previous checkpoints instant or the stopwatches starting time */ public Instant getPreviousInstant() { return getPreviousCheckpoint().map(Checkpoint::getInstant).orElseGet(getStopwatch()::getStartInstant); } /** {@inheritDoc} */ @Override public boolean isSupported(@Nullable final TemporalField field) { return getInstant().isSupported(field); } /** * Duration between this checkpoint and the previous {@link Checkpoint} or the * stopwatches starting time if this is the first checkpoint * * @return the duration between this checkpoint and previous checkpoints instant * or the stopwatches starting time */ public Duration sincePrevious() { return Duration.between(getPreviousInstant(), getInstant()); } /** * Duration between this checkpoint and the stopwatches start * * @return the duration between this checkpoint and the stopwatches start */ public Duration sinceStart() { return Duration.between(getStopwatch().getStartInstant(), getInstant()); } @java.lang.SuppressWarnings("all") @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code") @lombok.Generated public Stopwatch getStopwatch() { return this.stopwatch; } @java.lang.SuppressWarnings("all") @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code") @lombok.Generated public String getName() { return this.name; } @java.lang.SuppressWarnings("all") @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code") @lombok.Generated public Instant getInstant() { return this.instant; } @java.lang.SuppressWarnings("all") @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code") @lombok.Generated public Optional getPreviousCheckpoint() { return this.previousCheckpoint; } @java.lang.Override @java.lang.SuppressWarnings("all") @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code") @lombok.Generated public java.lang.String toString() { return "Stopwatch.Checkpoint(instant=" + this.getInstant() + ", name=" + this.getName() + ", previousCheckpoint=" + this.getPreviousCheckpoint() + ", stopwatch=" + this.getStopwatch() + ")"; } @java.lang.Override @java.lang.SuppressWarnings("all") @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code") @lombok.Generated public boolean equals(@Nullable final java.lang.Object o) { if (o == this) return true; if (!(o instanceof Stopwatch.Checkpoint)) return false; final Stopwatch.Checkpoint other = (Stopwatch.Checkpoint) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$name = this.getName(); final java.lang.Object other$name = other.getName(); if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false; final java.lang.Object this$instant = this.getInstant(); final java.lang.Object other$instant = other.getInstant(); if (this$instant == null ? other$instant != null : !this$instant.equals(other$instant)) return false; final java.lang.Object this$previousCheckpoint = this.getPreviousCheckpoint(); final java.lang.Object other$previousCheckpoint = other.getPreviousCheckpoint(); if (this$previousCheckpoint == null ? other$previousCheckpoint != null : !this$previousCheckpoint.equals(other$previousCheckpoint)) return false; return true; } @java.lang.SuppressWarnings("all") @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code") @lombok.Generated protected boolean canEqual(@Nullable final java.lang.Object other) { return other instanceof Stopwatch.Checkpoint; } @java.lang.Override @java.lang.SuppressWarnings("all") @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code") @lombok.Generated public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $name = this.getName(); result = result * PRIME + ($name == null ? 43 : $name.hashCode()); final java.lang.Object $instant = this.getInstant(); result = result * PRIME + ($instant == null ? 43 : $instant.hashCode()); final java.lang.Object $previousCheckpoint = this.getPreviousCheckpoint(); result = result * PRIME + ($previousCheckpoint == null ? 43 : $previousCheckpoint.hashCode()); return result; } @java.lang.SuppressWarnings("all") @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code") @lombok.Generated protected Checkpoint(final Stopwatch stopwatch, final String name, final Instant instant, final Optional previousCheckpoint) { this.stopwatch = stopwatch; this.name = name; this.instant = instant; this.previousCheckpoint = previousCheckpoint; } } /** * Instant at the stopwatches start * * @return the instant at the stopwatches start time */ @java.lang.SuppressWarnings("all") @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code") @lombok.Generated public Instant getStartInstant() { return this.startInstant; } @java.lang.Override @java.lang.SuppressWarnings("all") @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code") @lombok.Generated public java.lang.String toString() { return "Stopwatch(checkpoints=" + this.getCheckpoints() + ", startInstant=" + this.getStartInstant() + ")"; } @java.lang.SuppressWarnings("all") @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code") @lombok.Generated public Stopwatch() { } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy