
Adding some lessons learned over the years to Vinnie's answer, because it's not immediately obvious from the ASIO documentation... You should normally think of an io_context as a global dependency of the application. Create it in (or near) main() and pass a reference to it to every component of your application that needs access to an io_context. There are a couple of models for using ASIO: * one io_service, one thread - initialise your io_service with an argument of (1) to hint to ASIO that it can optimise for singfle-threaded code * one io_service, N threads - default-initialise your io_service and use strands to prevent contention in handlers. * N threads with one io_service per thread - a very efficient model, which will require you to manually load-balance connections by allocating them to the io_context associated with the least current load. This should probably not be attempted on your first try with ASIO. There are some other things that are not always obvious: * Many people keep shared_ptr's to sockets, deadline_timers and so on. This is an error. All ASIO io objects are moveable. Store by value. * SSL contexts are similar to io_contexts. There should be one (or perhaps two if you're both accepting inbound connections and making outbound connections) per application. Pass them by reference to your client/server objects. Storing an ssl::context in an object makes it non-moveable and is an error. * Good ASIO development is aided by the principle of dependency injection. * ASIO is easy to test - look at the methods io_context::poll(), io_context::run_one(), io_context::stopped(), io_context::restart() and io_context::strand::running_in_this_thread(). You can essentially single-step ASIO in your unit tests. This is a strong reason for using dependency injection (i.e. pass configuration data, contexts and executors by reference). * If you're multi-threading you'll either want to protect your objects with mutexes (not so efficient) or strands (really efficient). However, don't mix the models. If you're using strands then all access to your object from outside should be via an async function which takes a closure and posts an implementation of itself to the current object's strand. This ensures that everything runs in the correct thread (which you can assert with strand::running_in_this_thread() in your handler functions). On Thu, 20 Dec 2018 at 11:14, Vinnie Falco via Boost <boost@lists.boost.org> wrote:
On Wed, Dec 19, 2018 at 4:30 PM hh h via Boost <boost@lists.boost.org> wrote:
In many examples and even implementations, programmers like to pass boost::asio::io_service by raw pointer:
Those examples are wrong. `io_context` should be passed by reference.
Will this cause issues to pass raw pointer for large size of classes, should it be replaced by passing smart pointer:
A smart pointer is less efficient than a pointer, all else equal. But you shouldn't be using any form of pointer, the io_context (legacy name: io_service) is passed by reference. All of the Beast and Asio examples demonstrate this:
<https://github.com/boostorg/beast/tree/develop/example> <https://github.com/boostorg/asio/tree/develop/example>
Regards
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- Richard Hodges hodges.r@gmail.com office: +442032898513 home: +376841522 mobile: +376380212 (this will be *expensive* outside Andorra!) skype: madmongo facebook: hodges.r