00001 #ifndef H_CANOPEN_TIMER 00002 #define H_CANOPEN_TIMER 00003 00004 #include <socketcan_interface/FastDelegate.h> 00005 #include <boost/asio.hpp> 00006 #include <boost/thread/thread.hpp> 00007 #include <boost/asio/high_resolution_timer.hpp> 00008 00009 namespace canopen{ 00010 00011 class Timer{ 00012 public: 00013 typedef fastdelegate::FastDelegate0<bool> TimerDelegate; 00014 Timer():work(io), timer(io),thread(fastdelegate::FastDelegate0<size_t>(&io, &boost::asio::io_service::run)){ 00015 } 00016 00017 void stop(){ 00018 boost::mutex::scoped_lock lock(mutex); 00019 timer.cancel(); 00020 } 00021 template<typename T> void start(const TimerDelegate &del, const T &dur, bool start_now = true){ 00022 boost::mutex::scoped_lock lock(mutex); 00023 delegate = del; 00024 period = boost::chrono::duration_cast<boost::chrono::high_resolution_clock::duration>(dur); 00025 if(start_now){ 00026 timer.expires_from_now(period); 00027 timer.async_wait(fastdelegate::FastDelegate1<const boost::system::error_code&>(this, &Timer::handler)); 00028 } 00029 } 00030 void restart(){ 00031 boost::mutex::scoped_lock lock(mutex); 00032 timer.expires_from_now(period); 00033 timer.async_wait(fastdelegate::FastDelegate1<const boost::system::error_code&>(this, &Timer::handler)); 00034 } 00035 const boost::chrono::high_resolution_clock::duration & getPeriod(){ 00036 boost::mutex::scoped_lock lock(mutex); 00037 return period; 00038 } 00039 ~Timer(){ 00040 io.stop(); 00041 thread.join(); 00042 } 00043 00044 private: 00045 boost::asio::io_service io; 00046 boost::asio::io_service::work work; 00047 boost::asio::high_resolution_timer timer; 00048 boost::chrono::high_resolution_clock::duration period; 00049 boost::mutex mutex; 00050 boost::thread thread; 00051 00052 TimerDelegate delegate; 00053 void handler(const boost::system::error_code& ec){ 00054 if(!ec){ 00055 boost::mutex::scoped_lock lock(mutex); 00056 if(delegate && delegate()){ 00057 timer.expires_at(timer.expires_at() + period); 00058 timer.async_wait(fastdelegate::FastDelegate1<const boost::system::error_code&>(this, &Timer::handler)); 00059 } 00060 00061 } 00062 } 00063 }; 00064 00065 } 00066 00067 #endif