Can I create a software watchdog timer thread in C++ using Boost Signals2 and Threads?

后端 未结 4 2141
走了就别回头了
走了就别回头了 2020-12-06 06:28

I am running function Foo from somebody else\'s library in a single-threaded application currently. Most of the time, I make a call to Foo and it\'s really quick, some time

4条回答
  •  忘掉有多难
    2020-12-06 07:06

    You can use the following class:

    class timer
    {
        typedef boost::signals2::signal timeout_slot;
    public:
        typedef timeout_slot::slot_type timeout_slot_t;
    
    public:
        timer() : _interval(0), _is_active(false) {};
        timer(int interval) : _interval(interval), _is_active(false) {};
        virtual ~timer() { stop(); };
    
        inline boost::signals2::connection connect(const timeout_slot_t& subscriber) { return _signalTimeout.connect(subscriber); };
    
        void start()
        {
            boost::lock_guard lock(_guard);
    
            if (is_active())
                return; // Already executed.
            if (_interval <= 0)
                return;
    
            _timer_thread.interrupt();
            _timer_thread.join();
    
            timer_worker job;
            _timer_thread = boost::thread(job, this);
    
            _is_active = true;
        };
    
        void stop()
        {
            boost::lock_guard lock(_guard);
    
            if (!is_active())
                return; // Already executed.
    
            _timer_thread.interrupt();
            _timer_thread.join();
    
            _is_active = false;
        };
    
        inline bool is_active() const { return _is_active; };
    
        inline int get_interval() const { return _interval; };
    
        void set_interval(const int msec)
        {
            if (msec <= 0 || _interval == msec)
                return;
    
            boost::lock_guard lock(_guard);
            // Keep timer activity status.
            bool was_active = is_active();
    
            if (was_active)
                stop();
            // Initialize timer with new interval.
            _interval = msec;
    
            if (was_active)
                start();
        };
    
    protected:
        friend struct timer_worker;
        // The timer worker thread.
        struct timer_worker
        {
            void operator()(timer* t)
            {
                boost::posix_time::milliseconds duration(t->get_interval());
    
                try
                {
                    while (1)
                    {
                        boost::this_thread::sleep(duration);
                        {
                            boost::this_thread::disable_interruption di;
                            {
                                t->_signalTimeout();
                            }
                        }
                    }
                }
                catch (boost::thread_interrupted const& )
                {
                    // Handle the thread interruption exception.
                    // This exception raises on boots::this_thread::interrupt.
                }
            };
        };
    
    protected:
        int             _interval;
        bool            _is_active;
    
        boost::mutex    _guard;
        boost::thread   _timer_thread;
    
        // Signal slots
        timeout_slot    _signalTimeout;
    };
    

    An example of usage:

    void _test_timer_handler()
    {
        std::cout << "_test_timer_handler\n";
    }
    
    BOOST_AUTO_TEST_CASE( test_timer )
    {
        emtorrus::timer timer;
    
        BOOST_CHECK(!timer.is_active());
        BOOST_CHECK(timer.get_interval() == 0);
    
        timer.set_interval(1000);
        timer.connect(_test_timer_handler);
    
        timer.start();
    
        BOOST_CHECK(timer.is_active());
    
        std::cout << "timer test started\n";
    
        boost::this_thread::sleep(boost::posix_time::milliseconds(5500));
    
        timer.stop();
    
        BOOST_CHECK(!timer.is_active());
        BOOST_CHECK(_test_timer_count == 5);
    }
    

提交回复
热议问题