The functions use_service, make_service, and has_service do not introduce data races as a result of concurrent calls to those functions from different threads.
template<class Service> typename Service::key_type&
use_service(execution_context& ctx);
Effects: If an object of type Service::key_type does not already exist in the execution_context set identified by ctx, creates an object of type Service, initialized as Service(ctx), and adds it to the set.
Returns: A reference to the corresponding service of ctx.
Remarks: The reference returned remains valid until a call to destroy.
template<class Service, class... Args> Service&
make_service(execution_context& ctx, Args&&... args);
Requires: A service object of type Service::key_type does not already exist in the execution_context set identified by ctx.
Effects: Creates an object of type Service, initialized as Service(ctx, forward<Args>(args)...), and adds it to the execution_context set identified by ctx.
Throws: service_already_exists if a corresponding service object of type Service::key_type is already present in the set.
Remarks: The reference returned remains valid until a call to destroy.
template<class Service> bool has_service(const execution_context& ctx) noexcept;
Returns: true if an object of type Service::key_type is present in ctx, otherwise false.