c++ - Safely interrupt C++11 blocking operation -
i have std::thread
uses boost's asio read serial port:
std::atomic<bool> quit(false); void serialthread() { try { asio::io_service io; asio::serial_port port(io); port.open("com9"); // yeay no port enumeration support! port.set_option(asio::serial_port_base::baud_rate(9600)); while (!quit) { asio::streambuf buf; asio::read_until(port, buf, "\n"); auto = asio::buffers_begin(buf.data()); string line(it, + buf.size()); dostuffwithline(line); } } catch (std::exception e) { cout << "serial thread error: " << e.what() << endl; } } void setupsignals() { // arrange `quit = true;` happens when ctrl-c pressed. } int main(int argc, char *argv[]) { setupsignals(); thread st(serialthread); st.join(); return 0; }
when press ctrl-c want cleanly exit thread, destructors called appropriately (some drivers on windows hate if don't close resources properly).
unfortunately can see, current code blocks in read_until()
when press ctrl-c nothing happen until new line of text received.
one solution use polling, this:
asio::async_read_until(port, buf, "\n", ...); while (!quit) io.poll();
but i'd rather not use polling. pretty inelegant. solution can see have std::condition_variable quitoriofinished
triggered either when quit
set true, or when read finishes. didn't write asio can't give condition variable wait on.
is there clean sane solution? in go use select
wait on multiple channels, 1 of them quit channel. can't see similar solution in c++ though.
use asio::signal_set
await int signal (control-c tends send interrupt).
when arrives, call cancel()
on io objects pending asynchronous operations. return error_code
equal boost::asio::error::operation_aborted
.
now, if have io_service::work
object, destruct , threads running io_service::run()
return, can join them.
note take care of synchronizing access io objects (e.g. when invoke cancel()
on them) because these objects not thread-safe, unlike io_service
, strand
.
Comments
Post a Comment