LCOV - code coverage report
Current view: top level - asiolink - interval_timer.cc (source / functions) Hit Total Coverage
Test: report.info Lines: 41 46 89.1 %
Date: 2012-05-15 Functions: 12 13 92.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 20 39 51.3 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
       2                 :            : //
       3                 :            : // Permission to use, copy, modify, and/or distribute this software for any
       4                 :            : // purpose with or without fee is hereby granted, provided that the above
       5                 :            : // copyright notice and this permission notice appear in all copies.
       6                 :            : //
       7                 :            : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
       8                 :            : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
       9                 :            : // AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
      10                 :            : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      11                 :            : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
      12                 :            : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      13                 :            : // PERFORMANCE OF THIS SOFTWARE.
      14                 :            : 
      15                 :            : #include <config.h>
      16                 :            : 
      17                 :            : #include <boost/bind.hpp>
      18                 :            : #include <boost/enable_shared_from_this.hpp>
      19                 :            : #include <boost/shared_ptr.hpp>
      20                 :            : 
      21                 :            : #include <exceptions/exceptions.h>
      22                 :            : 
      23                 :            : #include <asio.hpp>
      24                 :            : #include <asiolink/interval_timer.h>
      25                 :            : #include <asiolink/io_service.h>
      26                 :            : 
      27                 :            : namespace isc {
      28                 :            : namespace asiolink {
      29                 :            : 
      30                 :            : /// This class holds a call back function of asynchronous operations.
      31                 :            : /// To ensure the object is alive while an asynchronous operation refers
      32                 :            : /// to it, we use shared_ptr and enable_shared_from_this.
      33                 :            : /// The object will be destructed in case IntervalTimer has been destructed
      34                 :            : /// and no asynchronous operation refers to it.
      35                 :            : /// Please follow the link to get an example:
      36                 :            : /// http://think-async.com/asio/asio-1.4.8/doc/asio/tutorial/tutdaytime3.html#asio.tutorial.tutdaytime3.the_tcp_connection_class
      37                 :            : class IntervalTimerImpl :
      38                 :            :     public boost::enable_shared_from_this<IntervalTimerImpl>
      39                 :            : {
      40                 :            : private:
      41                 :            :     // prohibit copy
      42                 :            :     IntervalTimerImpl(const IntervalTimerImpl& source);
      43                 :            :     IntervalTimerImpl& operator=(const IntervalTimerImpl& source);
      44                 :            : public:
      45                 :            :     IntervalTimerImpl(IOService& io_service);
      46                 :            :     ~IntervalTimerImpl();
      47                 :            :     void setup(const IntervalTimer::Callback& cbfunc, const long interval);
      48                 :            :     void callback(const asio::error_code& error);
      49                 :            :     void cancel() {
      50                 :        120 :         timer_.cancel();
      51                 :        120 :         interval_ = 0;
      52                 :            :     }
      53                 :          0 :     long getInterval() const { return (interval_); }
      54                 :            : private:
      55                 :            :     // a function to update timer_ when it expires
      56                 :            :     void update();
      57                 :            :     // a function to call back when timer_ expires
      58                 :            :     IntervalTimer::Callback cbfunc_;
      59                 :            :     // interval in milliseconds
      60                 :            :     long interval_;
      61                 :            :     // asio timer
      62                 :            :     asio::deadline_timer timer_;
      63                 :            :     // interval_ will be set to this value in destructor in order to detect
      64                 :            :     // use-after-free type of bugs.
      65                 :            :     static const long INVALIDATED_INTERVAL = -1;
      66                 :            : };
      67                 :            : 
      68                 :        115 : IntervalTimerImpl::IntervalTimerImpl(IOService& io_service) :
      69         [ +  - ]:        115 :     interval_(0), timer_(io_service.get_io_service())
      70                 :        115 : {}
      71                 :            : 
      72                 :        345 : IntervalTimerImpl::~IntervalTimerImpl() {
      73                 :        115 :     interval_ = INVALIDATED_INTERVAL;
      74                 :        115 : }
      75                 :            : 
      76                 :            : void
      77                 :         19 : IntervalTimerImpl::setup(const IntervalTimer::Callback& cbfunc,
      78                 :            :                          const long interval)
      79                 :            : {
      80                 :            :     // Interval should not be less than or equal to 0.
      81         [ +  + ]:         19 :     if (interval <= 0) {
      82         [ +  - ]:          4 :         isc_throw(isc::BadValue, "Interval should not be less than or "
      83                 :            :                                  "equal to 0");
      84                 :            :     }
      85                 :            :     // Call back function should not be empty.
      86         [ +  + ]:         17 :     if (cbfunc.empty()) {
      87         [ +  - ]:          2 :         isc_throw(isc::InvalidParameter, "Callback function is empty");
      88                 :            :     }
      89                 :         16 :     cbfunc_ = cbfunc;
      90                 :         16 :     interval_ = interval;
      91                 :            :     // Set initial expire time.
      92                 :            :     // At this point the timer is not running yet and will not expire.
      93                 :            :     // After calling IOService::run(), the timer will expire.
      94                 :         16 :     update();
      95                 :         16 : }
      96                 :            : 
      97                 :            : void
      98                 :         31 : IntervalTimerImpl::update() {
      99                 :            :     try {
     100                 :            :         // Update expire time to (current time + interval_).
     101                 :         31 :         timer_.expires_from_now(boost::posix_time::millisec(interval_));
     102                 :            :         // Reset timer.
     103                 :            :         // Pass a function bound with a shared_ptr to this.
     104                 :            :         timer_.async_wait(boost::bind(&IntervalTimerImpl::callback,
     105                 :            :                                       shared_from_this(),
     106 [ +  - ][ +  - ]:         31 :                                       asio::placeholders::error));
     107      [ #  #  # ]:          0 :     } catch (const asio::system_error& e) {
     108 [ #  # ][ #  # ]:          0 :         isc_throw(isc::Unexpected, "Failed to update timer: " << e.what());
                 [ #  # ]
     109                 :          0 :     } catch (const boost::bad_weak_ptr&) {
     110                 :            :         // Can't happen. It means a severe internal bug.
     111                 :          0 :         assert(0);
     112                 :            :     }
     113                 :         31 : }
     114                 :            : 
     115                 :            : void
     116                 :         20 : IntervalTimerImpl::callback(const asio::error_code& ec) {
     117         [ -  + ]:         20 :     assert(interval_ != INVALIDATED_INTERVAL);
     118 [ +  + ][ +  + ]:         38 :     if (interval_ == 0 || ec) {
                 [ +  + ]
     119                 :            :         // timer has been canceled. Do nothing.
     120                 :            :     } else {
     121                 :            :         // Set next expire time.
     122                 :         15 :         update();
     123                 :            :         // Invoke the call back function.
     124                 :         15 :         cbfunc_();
     125                 :            :     }
     126                 :         20 : }
     127                 :            : 
     128                 :        115 : IntervalTimer::IntervalTimer(IOService& io_service) :
     129         [ +  - ]:        115 :     impl_(new IntervalTimerImpl(io_service))
     130                 :        115 : {}
     131                 :            : 
     132                 :        230 : IntervalTimer::~IntervalTimer() {
     133                 :            :     // Cancel the timer to make sure cbfunc_() will not be called any more.
     134         [ +  - ]:        115 :     cancel();
     135                 :        115 : }
     136                 :            : 
     137                 :            : void
     138                 :         19 : IntervalTimer::setup(const Callback& cbfunc, const long interval) {
     139                 :         19 :     return (impl_->setup(cbfunc, interval));
     140                 :            : }
     141                 :            : 
     142                 :            : void
     143                 :        120 : IntervalTimer::cancel() {
     144                 :        120 :     impl_->cancel();
     145                 :        120 : }
     146                 :            : 
     147                 :            : long
     148                 :         10 : IntervalTimer::getInterval() const {
     149                 :         10 :     return (impl_->getInterval());
     150                 :            : }
     151                 :            : 
     152                 :            : } // namespace asiolink
     153 [ +  - ][ +  - ]:         30 : } // namespace isc

Generated by: LCOV version 1.9