libmoost
/home/mhx/git/github/libmoost/include/moost/process/sleeper.hpp
Go to the documentation of this file.
00001 /* vim:set ts=3 sw=3 sts=3 et: */
00028 #ifndef FM_LAST_MOOST_PROCESS_SLEEPER_H_
00029 #define FM_LAST_MOOST_PROCESS_SLEEPER_H_
00030 
00031 #include <boost/asio.hpp>
00032 #include <boost/date_time/posix_time/posix_time.hpp>
00033 #include <boost/shared_ptr.hpp>
00034 #include <boost/noncopyable.hpp>
00035 #include <boost/enable_shared_from_this.hpp>
00036 
00047 namespace moost { namespace process {
00048 
00049 class sleeper : public boost::noncopyable
00050 {
00051 private:
00052    // This helper class avoids creating all the io_service and deadline_timer cruft right away.
00053    // It might be a user of moost::process::sleeper doesn't even go beyond creating an instance.
00054    class impl : public boost::enable_shared_from_this<impl>, public boost::noncopyable
00055    {
00056    public:
00057       impl()
00058         : m_sleeping(false)
00059         , m_ios()
00060         , m_timer(m_ios)
00061       {
00062       }
00063 
00064       void sleep()
00065       {
00066          if (!m_sleeping)
00067          {
00068             m_sleeping = true;
00069             on_timer();
00070             m_ios.run();
00071          }
00072       }
00073 
00074       void awaken()
00075       {
00076          m_sleeping = false;
00077          m_timer.cancel();
00078       }
00079 
00080    private:
00081       void on_timer()
00082       {
00083          if (m_sleeping)
00084          {
00085             m_timer.expires_from_now(boost::posix_time::time_duration(boost::posix_time::pos_infin));
00086             m_timer.async_wait(boost::bind(&impl::on_timer, shared_from_this()));
00087          }
00088       }
00089 
00090       bool m_sleeping;
00091       boost::asio::io_service m_ios;
00092       boost::asio::deadline_timer m_timer;
00093    };
00094 
00095 public:
00096    sleeper()
00097    {
00098    }
00099 
00100    void sleep()
00101    {
00102       if (!m_impl)
00103       {
00104          m_impl.reset(new impl());
00105       }
00106 
00107       m_impl->sleep();
00108    }
00109 
00110    void awaken()
00111    {
00112       if (m_impl)
00113       {
00114          m_impl->awaken();
00115       }
00116    }
00117 
00118 private:
00119    boost::shared_ptr<impl> m_impl;
00120 };
00121 
00122 } }
00123 
00124 #endif