Browse Source

supported new methods for the interval timer: getting interval and canceling
the timer.

JINMEI Tatuya 14 years ago
parent
commit
a5c8450e8e

+ 14 - 1
src/lib/asiolink/asiolink.cc

@@ -386,6 +386,10 @@ public:
     void setupTimer(const IntervalTimer::Callback& cbfunc,
                     const uint32_t interval);
     void callback(const asio::error_code& error);
+    void cancel() {
+        timer_.cancel();
+        interval_ = 0;
+    }
     uint32_t getInterval() const { return (interval_); }
 private:
     // a function to update timer_ when it expires
@@ -399,7 +403,7 @@ private:
 };
 
 IntervalTimerImpl::IntervalTimerImpl(IOService& io_service) :
-    timer_(io_service.get_io_service())
+    interval_(0), timer_(io_service.get_io_service())
 {}
 
 IntervalTimerImpl::~IntervalTimerImpl()
@@ -428,6 +432,10 @@ IntervalTimerImpl::setupTimer(const IntervalTimer::Callback& cbfunc,
 
 void
 IntervalTimerImpl::updateTimer() {
+    if (interval_ == 0) {
+        // timer has been canceled.  Do nothing.
+        return;
+    }
     try {
         // Update expire time to (current time + interval_).
         timer_.expires_from_now(boost::posix_time::seconds(interval_));
@@ -462,6 +470,11 @@ IntervalTimer::setupTimer(const Callback& cbfunc, const uint32_t interval) {
     return (impl_->setupTimer(cbfunc, interval));
 }
 
+void
+IntervalTimer::cancel() {
+    impl_->cancel();
+}
+
 uint32_t
 IntervalTimer::getInterval() const {
     return (impl_->getInterval());

+ 20 - 1
src/lib/asiolink/asiolink.h

@@ -658,7 +658,26 @@ public:
     ///
     void setupTimer(const Callback& cbfunc, const uint32_t interval);
 
-    /// TBD
+    /// Cancel the timer.
+    ///
+    /// If the timer has been set up, this method cancels any asynchronous
+    /// events waiting on the timer and stops the timer itself.
+    /// If the timer has already been canceled, this method effectively does
+    /// nothing.
+    ///
+    /// This method never throws an exception.
+    void cancel();
+
+    /// Return the timer interval.
+    ///
+    /// This method returns the timer interval in seconds if it's running;
+    /// if the timer has been canceled it returns 0.
+    ///
+    /// This method never throws an exception.
+    ///
+    /// Note: We may want to change the granularity of the timer to
+    /// milliseconds or even finer.  If and when this happens the semantics
+    /// of the return value of this method will be changed accordingly.
     uint32_t getInterval() const;
 
 private:

+ 31 - 1
src/lib/asiolink/tests/asiolink_unittest.cc

@@ -751,7 +751,7 @@ TEST_F(ASIOLinkTest, recursiveTimeout) {
 // or not.
 class IntervalTimerTest : public ::testing::Test {
 protected:
-    IntervalTimerTest() : io_service_() {};
+    IntervalTimerTest() : io_service_() {}
     ~IntervalTimerTest() {}
     class TimerCallBack : public std::unary_function<void, void> {
     public:
@@ -811,6 +811,19 @@ protected:
         int count_;
         int prev_counter_;
     };
+    class TimerCallBackCanceller {
+    public:
+        TimerCallBackCanceller(unsigned int& counter, IntervalTimer& itimer) :
+            counter_(counter), itimer_(itimer)
+        {}
+        void operator()() {
+            ++counter_;
+            itimer_.cancel();
+        }
+    private:
+        unsigned int& counter_;
+        IntervalTimer& itimer_;
+    };
     class TimerCallBackOverwriter : public std::unary_function<void, void> {
     public:
         TimerCallBackOverwriter(IntervalTimerTest* test_obj,
@@ -927,6 +940,23 @@ TEST_F(IntervalTimerTest, destructIntervalTimer) {
     EXPECT_TRUE(timer_cancel_success_);
 }
 
+TEST_F(IntervalTimerTest, cancel) {
+    // Similar to destructIntervalTimer test, but the first timer explicitly
+    // cancels itself on first callback.
+    IntervalTimer itimer_counter(io_service_);
+    IntervalTimer itimer_watcher(io_service_);
+    unsigned int counter = 0;
+    itimer_counter.setupTimer(TimerCallBackCanceller(counter, itimer_counter),
+                              1);
+    itimer_watcher.setupTimer(TimerCallBack(this), 3);
+    io_service_.run();
+    EXPECT_EQ(1, counter);
+    EXPECT_EQ(0, itimer_counter.getInterval());
+
+    // canceling an already canceled timer shouldn't cause any surprise.
+    EXPECT_NO_THROW(itimer_counter.cancel());
+}
+
 TEST_F(IntervalTimerTest, overwriteIntervalTimer) {
     // Note: This test currently takes 4 seconds. The timer should have
     // finer granularity and timer periods in this test should be shorter