Thanks Richard and Vinnie, that was indeed comprehensive.
* 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.
That is the crux of clarifying to my post, so the io_service, context, sockets, deadline_times should all be stored by value not the shared pointer.
* 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.
In my server, there are mixed connections per application, the ssl is
used for applications provided services and connections via the
Internet, and non-ssl connections are used for applications provided
internal services withing the could (I believe it should not have
security issues). I am going to use one global io_service and one
global context for both ssl and non-ssl (which did nothing about ssl
context) applications, I think it should be fine, but appreciate your
inside opinion.
Thank you very much and appreciate it.
- JHH
On 12/20/18, Richard Hodges via Boost
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
wrote: On Wed, Dec 19, 2018 at 4:30 PM hh h via Boost
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
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost