Class execution_context implements an extensible, type-safe, polymorphic set of services, indexed by service type.
namespace std { namespace experimental { namespace net { inline namespace v1 { class execution_context { public: class service; // [async.exec.ctx.cons], construct / copy / destroy: execution_context(); execution_context(const execution_context&) = delete; execution_context& operator=(const execution_context&) = delete; virtual ~execution_context(); // [async.exec.ctx.ops], execution context operations: void notify_fork(fork_event e); protected: // [async.exec.ctx.protected], execution context protected operations: void shutdown() noexcept; void destroy() noexcept; }; // service access: template<class Service> typename Service::key_type& use_service(execution_context& ctx); template<class Service, class... Args> Service& make_service(execution_context& ctx, Args&&... args); template<class Service> bool has_service(const execution_context& ctx) noexcept; class service_already_exists : public logic_error { }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
Access to the services of an execution_context is via three function templates, use_service, make_service and has_service.
In a call to use_service<Service>, the type argument chooses a service, identified by Service::key_type, from a set of services in an execution_context. If the service is not present in the execution_context, an object of type Service is created and added to the execution_context. A program can check if an execution_context implements a particular service with the function template has_service<Service>.
Service objects may be explicitly added to an execution_context using the function template make_service<Service>. If the service is already present, make_service exits via an exception of type service_already_exists.
Once a service reference is obtained from an execution_context object by calling use_service, that reference remains usable until a call to destroy().
If a call to a specialization of use_service or make_service recursively calls another specialization of use_service or make_service which would choose the same service (identified by key_type) from the same execution_context, then the behavior is undefined. [ Note: Nested calls to specializations for different service types are well-defined. — end note ]
Effects: Creates an object of class execution_context which contains no services. [ Note: An implementation can preload services of internal service types for its own use. — end note ]
Effects: Destroys an object of class execution_context. Performs shutdown() followed by destroy().
Effects: For each service object svc in the execution_context set, in reverse order of addition to the set, performs svc->shutdown(). For each service in the set, svc->shutdown() is called only once irrespective of the number of calls to shutdown on the execution_context.
void destroy() noexcept;
Effects: Destroys each service object in the execution_context set, and removes it from the set, in reverse order of addition to the set.
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.