美文网首页
使用boost::asio::signal_set管理系统信号

使用boost::asio::signal_set管理系统信号

作者: FredricZhu | 来源:发表于2021-04-15 10:29 被阅读0次

    本例建立一个处理系统信号1,和系统信号SIGINT的signal_set,并在收到3次SIGINT后退出。
    使用Ctrl+C键可以向控制台应用程序发送SIGINT信号。
    CMakeLists.txt

    cmake_minimum_required(VERSION 2.6)
    project(lexical_cast)
    
    add_definitions(-std=c++14)
    
    include_directories("/usr/local/include")
    link_directories("/usr/local/lib")
    file( GLOB APP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
    foreach( sourcefile ${APP_SOURCES} )
        file(RELATIVE_PATH filename ${CMAKE_CURRENT_SOURCE_DIR} ${sourcefile})
        string(REPLACE ".cpp" "" file ${filename})
        add_executable(${file} ${sourcefile})
        target_link_libraries(${file} boost_filesystem boost_thread boost_system boost_serialization pthread boost_chrono)
    endforeach( sourcefile ${APP_SOURCES} )
    

    main.cpp

    #include "utils/tasks_processor_signal.hpp"
    
    using namespace tp_full;
    
    void accept_3_signals_and_stop(int signal) {
        static int signal_count = 0;
    
        assert(signal == SIGINT);
        ++ signal_count;
    
        std::cerr << "Captured " << signal_count << "SIGINT\n";
        if(signal_count == 3) {
            tasks_processor::get().stop();
        }
    }
    
    int main(int argc, char* argv[]) {
        // 注册的时候表示可以捕获 1和SIGINT两种信号
        // 捕获以后使用 accept_3_signals_and_stop 函数进行处理
        tasks_processor::get().register_signals_handler(
            &accept_3_signals_and_stop,
            std::vector<int>(1, SIGINT)
        );
    
        // 实际运行时只可能发送SIGINT信号,1是发不了的
        // Ctrl + C发送SIGINT
        tasks_processor::get().start();
    }
    

    tasks_processor_base.hpp

    #ifndef _CHAPTER06_05_TASKS_PROCESSOR_HPP_
    #define _CHAPTER06_05_TASKS_PROCESSOR_HPP_
    #include <boost/noncopyable.hpp>
    #include <boost/thread/thread.hpp>
    #include <boost/asio/io_service.hpp>
    
    #include <iostream>
    
    namespace detail {
        template <class T>
        struct task_wrapped {
            private:
                T task_unwrapped_;
    
            public:
                explicit task_wrapped(const T& task_unwrapped): task_unwrapped_(task_unwrapped) {}
    
                void operator()() const {
                    // 重置中断点
                    try {
                        boost::this_thread::interruption_point();
                    } catch(const boost::thread_interrupted&) {
    
                    }
    
                    try {
                        task_unwrapped_();
                        // boost大部分的异常均继承自std::exception类,所以
                        // 直接catch std::exception即可
                    } catch(const std::exception& e) {  
                        std::cerr << "Exception: " << e.what() << "\n";
                    } catch(const boost::thread_interrupted&) {
                        std::cerr << "Thread interrupted\n";
                    } catch(...) {
                        std::cerr << "Unknown exception\n";
                    }
                }  
        };
    
        template <class T>
        inline task_wrapped<T> make_task_wrapped(const T& task_unwrapped) {
            return task_wrapped<T>(task_unwrapped);
        }
    }; // namespace detail
    
    namespace tp_base {
        class tasks_processor: private boost::noncopyable {
            protected:
                boost::asio::io_service ios_;
                boost::asio::io_service::work work_;
    
                tasks_processor():
                    ios_(),
                    work_(ios_)
                 {}
            public:
                // 获取单例的tasks_processor对象的静态方法
                static tasks_processor& get();
    
                template <class T>
                inline void push_task(const T& task_unwrapped) {
                    ios_.post(detail::make_task_wrapped(task_unwrapped));
                }
    
                void start() {
                    ios_.run();
                }
    
                void stop() {
                    ios_.stop();
                }
        };
    }; // namespace tp_base
    
    #endif
    

    tasks_processor_multithread.hpp

    #ifndef _CHAPTOR06_05_TASKS_PROCESSOR_MULTITHREAD_HPP_
    #define _CHAPTOR06_05_TASKS_PROCESSOR_MULTITHREAD_HPP_
    
    #include "tasks_processor_base.hpp"
    
    namespace tp_multithread {
    
        
        class tasks_processor: public tp_base::tasks_processor {
            public:
                // 获取单例的tasks_processor对象的静态方法
                static tasks_processor& get();
    
                void start_multiple(std::size_t threads_count = 0) {
                    if(!threads_count) {
                        threads_count = (std::max)(
                            static_cast<int>(boost::thread::hardware_concurrency()),
                            1
                        );
                    }
    
                    // 去除掉当前线程
                    -- threads_count;
                    boost::thread_group tg;
                    for(std::size_t i=0; i<threads_count; ++i) {
                        tg.create_thread([this]() {
                            this->ios_.run();
                        });
                    }
    
                    ios_.run();
                    tg.join_all();
                }
        };
    };
    #endif
    

    tasks_processor_signal.hpp

    #ifndef _CHAPTOR06_07_TASKS_PROCESSOR_SIGNALS_HPP_
    #define _CHAPTOR06_07_TASKS_PROCESSOR_SIGNALS_HPP_
    
    #include "tasks_processor_multithread.hpp"
    
    #include <boost/asio/signal_set.hpp>
    #include <boost/function.hpp>
    
    namespace tp_full {
    
        class tasks_processor: public tp_multithread::tasks_processor {
            private:
                tasks_processor():
                    tp_multithread::tasks_processor(),
                    signals_(ios_)
                 {}
    
                boost::asio::signal_set signals_;
                boost::function<void(int)> users_signal_handler_;
    
                void handle_signals(
                    const boost::system::error_code& ec,
                    int signal_number
                ) {
                    if(ec) {
                        std::cerr << "Error in signal handling: " << ec << '\n';
                    } {
                        // 处理当前signal事件
                        detail::make_task_wrapped([this, signal_number](){
                            this->users_signal_handler_(signal_number);
                        })  
                            ();
                    }
    
                    // 等待下一个signal
                    signals_.async_wait([this](const boost::system::error_code& ec, int sign_number){
                        this->handle_signals(ec, sign_number);
                    });
                }
            
            public:
                static tasks_processor& get();
                
                template <class Func> 
                void register_signals_handler(const Func& f,
                    const std::vector<int>& signals_to_wait) {
                    // 确认是首次注册
                    assert(!users_signal_handler_);
    
                    users_signal_handler_ = f;
                    // 注册信号到信号集
                    std::for_each(signals_to_wait.begin(),
                        signals_to_wait.end(),
                        [this](const int signal_num) {
                            this->signals_.add(signal_num);
                        });
                    
                    // 等待信号集中的信号发生,调用处理函数
                    signals_.async_wait([this](
                        const boost::system::error_code& ec,
                        int signal_num
                    ){
                        this->handle_signals(ec, signal_num);
                    });
                }
        };
    
        tasks_processor& tasks_processor::get() {
            static tasks_processor proc;
            return proc;
        }
    };
    
    #endif
    

    程序输出如下,


    图片.png

    相关文章

      网友评论

          本文标题:使用boost::asio::signal_set管理系统信号

          本文链接:https://www.haomeiwen.com/subject/oahdlltx.html