2

I am using Boost.Asio and Boost.Thread. How can I cancel a synchronous IO operation in a secondary Thread? For example,

/* consider needed headers included and typedefs are defined */

void OperationThread(sock_ptr sock) {
  char buf[128];
  boost::system::error_code ec;
  boost::asio::read(*sock, boost::asio::buffer(buf, 128), ec);
}

void AcceptorThread() {
  boost::asio::io_service serv;
  boost_asio_endpoint_type ep( ... /* v4() etc. */ , ... /* port */ );
  boost_asio_acceptor_type acc(serv, ep);
  sock_ptr sock(new boost_asio_socket_type(serv));
  while (true) {
    acc.accept(*sock);
    boost::thread t(boost::bind(&OperationThread, sock)); // new thread
    sock.reset(new boost_asio_socket_type(serv)); // new socket
  }
}

int main() {
  boost::thread accthread(&AcceptorThread);
  cin.get();
  // Code to cancel synchronous accept operation and read operations
  return 0;
}

sock_ptr is a typedef of boost::shared_ptr<boost_asio_socket_type>.

If you get confused about boost_asio_*_type consider they are configured for boost::asip::ip::tcp and v4().

First of all I used to use asynchronous operations. But you know they are a little bit hard to manage. And I want one-thread-per-connection application model. It's harder to implement it using asynchronous IO (actually I don't know how to implement it, how can I poll a specific asynchronous operation in a thread?, I'd be happy if you mention.). So I use synchronous IO.

And in my code, as you would notice, my thread object destroyed at the end of while block. Does it make any harm? (sorry I know it is not appropriate to ask it in this question, but anyone who wants to do what I am trying to do may face this question. So if you answer, I will be very happy. ʘ‿ʘ)

Thanks.

jnbrq -Canberk Sönmez
  • 1,790
  • 1
  • 17
  • 29
  • Asio does not provide a way to cancel synchronous operations (see this [answer](http://stackoverflow.com/a/11195223/1053968) for similar question). Also, if someone is struggling with the inverted flow control from asynchronous programming, then I strongly suggest utilizing Asio's coroutine support (see this [answer](http://stackoverflow.com/a/13997290/1053968)). – Tanner Sansbury Jul 17 '15 at 16:09

1 Answers1

0

Yes you can, as long as you propoerly synchronize access to the service object (e.g. boost::asio::ip::tcp::socket or boost::asio::deadline_timer)¹.

In your code, additionally, you'd be using the shared_ptr<> from different threads. Shared pointers are not thread safe per se. Although you can use the atomic_load and atomic_store functions with them to make it thread-safe.


¹ The documentation reveals the (exceptional) cases where objects are thread safe. The only two I can cite from memory are boost::asio::io_service and boost::asio::strand

sehe
  • 374,641
  • 47
  • 450
  • 633
  • OK. Could you provide a pseudo-code to your answer? If you couldn't, at least, could you link to the documentation or an example? – jnbrq -Canberk Sönmez Jul 17 '15 at 10:28
  • Here's a link to the docs: http://www.boost.org/doc/libs/1_58_0/doc/html/boost_asio/overview/core/threads.html I don't know what to write because I'm not sure what you want to achieve. I believe the tutorials/examples show everything you are trying to do – sehe Jul 17 '15 at 10:30
  • Thank you for the information about thread safety of `shared_ptr`. – jnbrq -Canberk Sönmez Jul 17 '15 at 10:30
  • Could you give any idea about polling specific asynchronous operations on specific threads? It would be better to know. – jnbrq -Canberk Sönmez Jul 17 '15 at 10:33
  • See http://stackoverflow.com/questions/7362894/boostasiosocket-thread-safety and http://stackoverflow.com/a/12801042/85371 – sehe Jul 17 '15 at 10:35
  • [In this official example](http://www.boost.org/doc/libs/1_52_0/doc/html/boost_asio/example/echo/blocking_tcp_echo_server.cpp) there is no use of thread safe `shared_ptr`. That example looks really like mine. So could you explain why did you recommend making `shared_ptr` thread safe? – jnbrq -Canberk Sönmez Jul 17 '15 at 11:06
  • I didn't recommend that. I said that if you access the same shared pointer from multiple threads you _need to_ synchronize access. Of course, if you do not (as that linked sample) you're fine – sehe Jul 17 '15 at 11:07
  • There are a lot of sub-questions in this single question, but for what it is worth, I do not think Asio provides an official way to cancel synchronous operations. – Tanner Sansbury Jul 17 '15 at 16:18
  • @TannerSansbury I suppose canceling the wait for them counts? http://www.boost.org/doc/libs/1_58_0/doc/html/boost_asio/reference/basic_stream_socket/cancel.html – sehe Jul 17 '15 at 16:20
  • @sehe As far as I know, cancel only affects outstanding _asynchronous_ operations, not _synchronous_ operations. In theory, one could close the socket, but that would be a violation of the thread safety for the I/O object. – Tanner Sansbury Jul 17 '15 at 16:27
  • Darn. I tripped over the question title. I read "cancel a synchronous" as "cancel asynchronus" – sehe Jul 17 '15 at 16:28
  • Haha. It took me far too long than I would like to admit to stop myself from verbally saying "a synchronous" while presenting. (: – Tanner Sansbury Jul 17 '15 at 16:34