diff --git a/CPS/src/lu/list/itis/dkd/tui/utility/ThrottlingExecutor.java b/CPS/src/lu/list/itis/dkd/tui/utility/ThrottlingExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..eee6c8ad909582bc52536518738bf9c45635d5d1 --- /dev/null +++ b/CPS/src/lu/list/itis/dkd/tui/utility/ThrottlingExecutor.java @@ -0,0 +1,123 @@ +/** + * Copyright Luxembourg Institute of Science and Technology, 2020. All rights reserved. If you wish + * to use this code for any purpose, please contact the author(s). + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package lu.list.itis.dkd.tui.utility; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.TimerTask; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +/** + * @author nico.mack@list.lu + * @since 2.8 + * @version 1.0.0 + */ +// *************************************************************************** +// * Class Definition * +// *************************************************************************** + +public class ThrottlingExecutor { + + private long last; + private ScheduledFuture scheduled; + private long coalescePeriod; + + private static ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + + // *************************************************************************** + // * Constants * + // *************************************************************************** + + private static final Logger LOGGER = LoggerFactory.getLogger(ThrottlingExecutor.class.getSimpleName()); + + // --------------------------------------------------------------------------- + // *************************************************************************** + // * Constructor(s) + // *************************************************************************** + // --------------------------------------------------------------------------- + + public ThrottlingExecutor() { + this.coalescePeriod = 0; + this.last = 0; + } + + // --------------------------------------------------------------------------- + // *************************************************************************** + // * Class Body + // *************************************************************************** + // --------------------------------------------------------------------------- + /** + * Method for setting the minimum time between subsequent calls to this end point. + * + * @param millis + * The minimum number of milliseconds between subsequent calls to this end point. + */ + // --------------------------------------------------------------------------- + + public void setCoalescePeriod(int millis) { + this.coalescePeriod = millis; + } + + // --------------------------------------------------------------------------- + /** + * Checks whether this end point was previously called without being ready. + * + * @return True if end point was called without being ready to be called, + * False otherwise. + */ + // --------------------------------------------------------------------------- + + public boolean isCallPending() { + return (scheduled != null); + } + + // --------------------------------------------------------------------------- + + public void submit(TimerTask task) { + long now = System.currentTimeMillis(); + + if ((this.coalescePeriod > 0) && (last > 0)) { + long elapsed = now - last; + + if (elapsed < this.coalescePeriod) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Task submitted within {} ms coalesce period! Deferred execution in {} ms!", this.coalescePeriod, (this.coalescePeriod - elapsed)); //$NON-NLS-1$ + } + + if (scheduled != null) { + scheduled.cancel(true); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Cancelled previously scheduled task!"); //$NON-NLS-1$ + } + + } + scheduled = executor.schedule(task, (this.coalescePeriod - elapsed), TimeUnit.MILLISECONDS); + return; + } + } + executor.schedule(task, 0, TimeUnit.MILLISECONDS); + last = now; + scheduled = null; + } + + // --------------------------------------------------------------------------- + // *************************************************************************** + // * End of Class + // *************************************************************************** + // --------------------------------------------------------------------------- +}