Hi all,

I started playing with ASIO timers and after scanning through the relevant docs, I set up a small case. Please find below the
code snippet.
The IntervalEvent class is supposed to fire the event provided on the construction at a frequency equal to the durationInterval.

Somehow the code below fails to compile on VC7.1.
I am getting several warnings and the error:
c:\program files\boost\boost_1_38\boost\mem_fn.hpp(343) : error C4716: 'boost::_mfi::dm<void __thiscall IntervalEvent::(boost::system::error_code &),IntervalEvent>::operator()' : must return a value

I have not tried yet gcc. Probably I am doing something stupid. Any ideas?

Further to that, I am wondering, in principle should I cancel the deadline_timer on the destructor of the IntervalEvent class? Does the io_service class know when any of the deadline_timers that is being registered goes out of scope?

Thank you very much in advance. Any help would be highly appreciated.

Kimon

#include <boost/function.hpp>
#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>



class Counter
{
public:
   Counter():m_value(0)
   {
   
   }
   void onIncrement()
   {
      ++m_value;
      std::cout<<"Counter is "<<m_value<<std::endl;
   }
protected:
   int m_value;
};

class IntervalEvent
{
public:
   IntervalEvent(boost::asio::io_service &io,
                 long durationSeconds,
         boost::function<void(void)> event):
    m_intervalDuration(durationSeconds),
    m_timer(io,boost::posix_time::seconds(m_intervalDuration)),
    m_event(event)
    {
        //io_service::run is running in only one thread
        m_timer.async_wait(boost::bind(&IntervalEvent::handler, this));
    }
    ~IntervalEvent()
    {
        //should I call m_timer.cancel to notify the io_service?
    }
    void handler(boost::system::error_code& error)
    {
        if(error!= boost::asio::error::operation_aborted)
        {
           m_event();
           reset(m_intervalDuration);
        }
    }
    void reset(long duration)
    {
        if (m_timer.expires_from_now(boost::posix_time::seconds(duration)) > 0)
        {
        m_intervalDuration = duration;
        //reset the async wait
        m_timer.async_wait(boost::bind(&IntervalEvent::handler, this));
        }
        else
        {
        //Timer already canceled
        }
    }
    void cancel()
    {
        m_timer.cancel();
    }
    size_t getCurrentInterval() const
    {
        return m_intervalDuration;
    }
protected:
    long m_intervalDuration;
    boost::asio::deadline_timer m_timer;
    boost::function<void(void)> m_event;
};

int main()
{

   boost::asio::io_service io;
   boost::shared_ptr<boost::asio::io_service::work> work(new boost::asio::io_service::work(io));

   boost::thread ioservice_thread(boost::bind(&boost::asio::io_service::run, &io));

   std::vector<boost::shared_ptr<IntervalEvent> > events;

   Counter count;
   long duration = 1;
   boost::shared_ptr<IntervalEvent> firstEvent(new IntervalEvent(io,
                                duration,
                                boost::bind(&Counter::onIncrement,boost::ref(count)
                                ))
                              );
   events.push_back(firstEvent);

   char response = 'N';
   while(response == 'N')
   {
       std::cout<<"Create a new interval event? [Y/N]"<<std::endl;
       std::cin>>response;
       if(response == 'Y')
       {
      boost::shared_ptr<IntervalEvent> test(new IntervalEvent(io,
                                          duration,
                                boost::bind(&Counter::onIncrement,boost::ref(count)
                                ))
                                     );
     events.push_back(test);
       }
   }
 
   //cancel interval events
   for(std::vector<boost::shared_ptr<IntervalEvent> >::iterator it = events.begin(), itEnd = events.end();
      it!=itEnd;
      ++it)
   {
    (*it)->cancel();
   }
   //reset ioservice_work
   work.reset();

   ioservice_thread.join();

   return 0;
}