001    /**
002     * Copyright (C) 2011-2012 Barchart, Inc. <http://www.barchart.com/>
003     *
004     * All rights reserved. Licensed under the OSI BSD License.
005     *
006     * http://www.opensource.org/licenses/bsd-license.php
007     */
008    package com.barchart.util.concurrent;
009    
010    import java.util.concurrent.Executors;
011    import java.util.concurrent.ScheduledExecutorService;
012    import java.util.concurrent.ScheduledFuture;
013    import java.util.concurrent.TimeUnit;
014    import java.util.concurrent.locks.Lock;
015    import java.util.concurrent.locks.ReentrantLock;
016    
017    import org.slf4j.Logger;
018    import org.slf4j.LoggerFactory;
019    
020    /**
021     * 
022     * @author jeremy
023     * 
024     */
025    public class RollingDelayTrigger {
026    
027            private static final Logger log = LoggerFactory
028                            .getLogger(RollingDelayTrigger.class);
029    
030            private final Lock lock = new ReentrantLock();
031            private final ScheduledExecutorService executor = Executors
032                            .newSingleThreadScheduledExecutor();
033            private ScheduledFuture<?> scheduledRestart;
034    
035            private final Runnable task;
036            private final long delay;
037            private final Runnable runner;
038    
039            public RollingDelayTrigger(final Runnable task_, final long delay_) {
040    
041                    task = task_;
042                    delay = delay_;
043                    runner = new TaskRunner();
044    
045            }
046    
047            /**
048             * Trigger a delayed task execution. If a task execution is already pending,
049             * its delay will be reset.
050             */
051            public void trigger() {
052    
053                    lock.lock();
054                    try {
055    
056                            cancel();
057                            scheduledRestart = executor.schedule(runner, delay,
058                                            TimeUnit.MILLISECONDS);
059    
060                    } finally {
061                            lock.unlock();
062                    }
063    
064            }
065    
066            /**
067             * Cancel any pending delayed tasks until the next call to trigger().
068             */
069            public void cancel() {
070    
071                    lock.lock();
072                    try {
073    
074                            if (scheduledRestart != null) {
075                                    scheduledRestart.cancel(false);
076                                    scheduledRestart = null;
077                            }
078    
079                    } finally {
080                            lock.unlock();
081                    }
082    
083            }
084    
085            private class TaskRunner implements Runnable {
086    
087                    @Override
088                    public void run() {
089    
090                            try {
091    
092                                    lock.lock();
093                                    try {
094                                            scheduledRestart = null;
095                                    } finally {
096                                            lock.unlock();
097                                    }
098    
099                                    task.run();
100    
101                            } catch (final Exception e) {
102                                    log.warn("Exception running delay trigger task", e);
103                            }
104    
105                    }
106    
107            }
108    
109    }