美文网首页
使用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