0

In my app I will receive various events that I would like to process asynchronously in a prioritised order.

I could do this with a boost::asio::io_service, but my application is single threaded. I don't want to pay for locks and mallocs you might need for a multi threaded program (the performance cost really is significant to me). I'm basically looking for a boost::asio::io_service that is written for single threaded execution.

I'm pretty sure I could implement this myself using boost::coroutine, but before I do, does something like a boost::asio::io_service that is written for single threaded execution exist already? I scanned the list of boost libraries already and nothing stood out to me

sehe
  • 374,641
  • 47
  • 450
  • 633
RichardBruce
  • 641
  • 2
  • 10
  • 19
  • you can put io_service::run() int main(); – thomas Sep 18 '14 at 02:36
  • 1
    Call `io_service::run()` from a [single thread](http://www.boost.org/doc/libs/1_56_0/doc/html/boost_asio/tutorial/tuttimer2.html). – Igor R. Sep 18 '14 at 04:41
  • @IgorR. of course internally, the service object will still lock its queue. But, I smell premature optimization. Just implement it using an interface that allows you to replace the nuts&bolts if you really do find that "all the synchronization" is killing your throughput/sending latency through the roof. – sehe Sep 18 '14 at 06:23
  • 1
    Would be good to know that locking overhead will be visible only after more than a couple hundred thousands ops per sec. That's well above 99% apps out there. Probably it's better to just go ahead and add that thread. – Sam Sep 18 '14 at 06:48

2 Answers2

2

Be aware that you have to pay for synchronization as soon as you use any non-blocking calls of Asio.

Even though you might use a single thread for scheduling work and processing the resulting callbacks, Asio might still have to spawn additional threads internally for executing asynchronous calls. Those will access the io_service concurrently.

Think of an async_read on a socket: As soon as the received data becomes available, the socket has to notify the io_service. This happens concurrent to your main thread, so additional synchronization is required.

For blocking I/O this problem goes away in theory, but since asynchronous I/O is sort of the whole point of the library, I would not expect to find too many optimizations for this case in the implementation.

As was pointed out in the comments already, the contention on the io_service will be very low with only one main thread, so unless profiling indicates a clear performance bottleneck there, you should not worry about it too much.

Community
  • 1
  • 1
ComicSansMS
  • 51,484
  • 14
  • 155
  • 166
1

I suggest to use boost::asio together with boost::coroutine -> boost::asio::yield_context (does already the coupling between coroutine + io_service). If you detect an task with higher priority you could suspend the current task and start processing the task with higher priority. The problem is that you have to define/call certain check-points in the code of your task in order to suspend the task if the condition (higher prio task enqueued) is given.

olk
  • 372
  • 1
  • 3