本例建立一个处理系统信号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
网友评论