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

org.openbase.jul.schedule.Stopwatch Maven / Gradle / Ivy

There is a newer version: 3.6.0
Show newest version
package org.openbase.jul.schedule;

/*
 * #%L
 * JUL Schedule
 * %%
 * Copyright (C) 2015 - 2018 openbase.org
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */
import org.openbase.jul.exception.CouldNotPerformException;
import org.openbase.jul.exception.InvalidStateException;
import org.openbase.jul.exception.NotAvailableException;

/**
 * @author Divine Threepwood
 *
 * This class implements a general purpose stopwatch.
 *
 * This implementation should be thread safe.
 */
public class Stopwatch {

    private final SyncObject startWaiter = new SyncObject("StartWaiter");
    private final SyncObject stopWaiter = new SyncObject("StopWaiter");
    private final SyncObject timeSync = new SyncObject("TimeSync");

    private long startTime, endTime;

    /**
     * Constructor initializes a new Stopwatch.
     */
    public Stopwatch() {
        reset();
    }

    /**
     * This method resets the Stopwatch by clearing the internally stored start and end timestamps.
     */
    public final void reset() {
        synchronized (timeSync) {
            this.startTime = -1;
            this.endTime = -1;
        }
    }

    /**
     * This method starts the Stopwatch by setting the start timestamp.
     */
    public void start() {
        synchronized (startWaiter) {
            synchronized (timeSync) {
                startTime = System.currentTimeMillis();
            }
            startWaiter.notifyAll();
        }
    }

    /**
     * This method restarts the Stopwatch.
     *
     * Internally the reset() and start() methods are called.
     */
    public void restart() {
        synchronized (timeSync) {
            reset();
            start();
        }
    }

    /**
     * This method returns the time interval between the start- and end timestamps.
     * In case the the Stopwatch is still running, the elapsed time since Stopwatch start will be returned.
     *
     * @return the time interval in milliseconds.
     * @throws NotAvailableException This exception will thrown in case the timer was never started.
     */
    public long getTime() throws NotAvailableException {
        synchronized (timeSync) {
            try {
                if (!isRunning()) {
                    throw new InvalidStateException("Stopwatch was never started!");
                }

                if (endTime == -1) {
                    return System.currentTimeMillis() - startTime;
                }

                return endTime - startTime;
            } catch (CouldNotPerformException ex) {
                throw new NotAvailableException("time", ex);
            }
        }
    }

    /**
     * Method checks if the Stopwatch was started after reset.
     *
     * Even after calling the stop method the Stopwatch is still running until reset() is called.
     *
     * @return true if the Stopwatch was started.
     */
    public boolean isRunning() {
        synchronized (timeSync) {
            return startTime != -1;
        }
    }

    /**
     * This method stops the Stopwatch and returns the time result.
     *
     * The internal timestamps are not cleared by this method so the result can still queried by the getTime() method afterwards.
     * Additionally this method can be called multiply times but only the last stop timestamp will be stored and handled by the getTime() method.
     *
     * @return the elapsed time interval since start.
     * @throws org.openbase.jul.exception.CouldNotPerformException is thrown in case the Stopwatch was never started.
     */
    public long stop() throws CouldNotPerformException {
        synchronized (timeSync) {
            if (!isRunning()) {
                throw new InvalidStateException("Stopwatch was never started!");
            }

            synchronized (stopWaiter) {
                endTime = System.currentTimeMillis();
                stopWaiter.notifyAll();
            }

            return getTime();
        }
    }

    /**
     * Method returns the timestamp of the Stopwatch start.
     *
     * @return the timestamp in milliseconds.
     * @throws org.openbase.jul.exception.NotAvailableException is thrown in case the Stopwatch was never started.
     */
    public long getStartTime() throws NotAvailableException {
        if (startTime == -1) {
            throw new NotAvailableException("StartTime");
        }
        return startTime;
    }

    /**
     * Method returns the timestamp of the last Stopwatch stop.
     *
     * @return the timestamp in milliseconds.
     * @throws org.openbase.jul.exception.NotAvailableException is thrown in case the Stopwatch was never started.
     */
    public long getEndTime() throws NotAvailableException {
        if (endTime == -1) {
            throw new NotAvailableException("StopTime");
        }
        return endTime;
    }

    /**
     * Method blocks until the Stopwatch start or the given timeout expired.
     *
     * @param timeout max time to wait.
     * @throws InterruptedException is thrown in case the current thread was externally interrupted.
     */
    public void waitForStart(final long timeout) throws InterruptedException {
        synchronized (startWaiter) {
            if (isRunning()) {
                return;
            }
            startWaiter.wait(timeout);
        }
    }

    /**
     * Method blocks until the Stopwatch start.
     *
     * @throws InterruptedException is thrown in case the current thread was externally interrupted.
     */
    public void waitForStart() throws InterruptedException {
        synchronized (startWaiter) {
            if (isRunning()) {
                return;
            }
            startWaiter.wait();
        }
    }

    /**
     * Method blocks until the Stopwatch stop or the given timeout expired.
     *
     * @param timeout max time to wait.
     * @throws InterruptedException is thrown in case the current thread was externally interrupted.
     */
    public void waitForStop(final long timeout) throws InterruptedException {
        synchronized (stopWaiter) {
            if (endTime != -1) {
                return;
            }
            stopWaiter.wait(timeout);
        }
    }

    /**
     * Method blocks until the Stopwatch stop.
     *
     * @throws InterruptedException is thrown in case the current thread was externally interrupted.
     */
    public void waitForStop() throws InterruptedException {
        synchronized (stopWaiter) {
            if (endTime != -1) {
                return;
            }
            stopWaiter.wait();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy