diff --git a/doc/channel.qbk b/doc/channel.qbk index 1f5da80d..8122f42e 100644 --- a/doc/channel.qbk +++ b/doc/channel.qbk @@ -116,9 +116,9 @@ that no more values will arrive.]] ] [xchannel_close unbounded_channel] -[template xchannel_push_effects[enqueues] If channel is not closed, -[enqueues] the value in the channel, wakes up a fiber blocked on -`this->pop()`, `this->value_pop()`, `this->pop_wait_for()` or +[template xchannel_push_effects[enqueues] If channel is closed, returns +`closed`. Otherwise [enqueues] the value in the channel, wakes up a fiber +blocked on `this->pop()`, `this->value_pop()`, `this->pop_wait_for()` or `this->pop_wait_until()` and returns `success`.] [member_heading unbounded_channel..push] @@ -175,7 +175,7 @@ dequeued value[unblocking]]] [xchannel_try_pop unbounded_channel .] [template xchannel_pop_wait_until_effects[endtime unblocking] If channel -iss not _empty, immediately dequeues a value from the channel. Otherwise +is not empty, immediately dequeues a value from the channel. Otherwise the fiber gets suspended until at least one new item is `push()`ed (return value `success` and `va` contains dequeued value), or the channel gets `close()`d (return value `closed`), or the system time reaches [endtime] @@ -302,7 +302,7 @@ in the channel is less than `hwm`.]] [xchannel_close bounded_channel] [template bounded_channel_push_effects[or] [xchannel_push_effects If channel -is not full, [enqueues] Otherwise the calling fiber is suspended until +is not full, enqueues] Otherwise the calling fiber is suspended until the number of values in the channel drops below `lwm` (return value `success`)[or] the channel is `close()`d (return value `closed`)] @@ -355,7 +355,7 @@ time_point (return value `timeout`).]] channel_op_status try_push( value_type && va); [variablelist -[[Effects:] [If is full, returns `full`. +[[Effects:] [If channel is full, returns `full`. [xchannel_push_effects Otherwise enqueues]]] [[Throws:] [__fiber_interrupted__]] ] diff --git a/doc/future.qbk b/doc/future.qbk index 8219d409..14d234bf 100644 --- a/doc/future.qbk +++ b/doc/future.qbk @@ -9,6 +9,24 @@ A future provides a mechanism to access the result of an asynchronous operation. +[#shared_state] +[heading shared state] + +Behind a [template_link promise] and its [template_link future] lies an +unspecified object called their ['shared state]. The shared state is what will +actually hold the async result (or the exception). + +The shared state is instantiated along with the [template_link promise]. + +Aside from its originating `promise<>`, a [template_link future] holds a +unique reference to a particular shared state. However, multiple +[template_link shared_future] instances can reference the same underlying +shared state. + +As [template_link packaged_task] and [ns_function_link fibers..async] are +implemented using [template_link promise], discussions of shared state apply +to them as well. + [#class_future_status] [heading Enumeration `future_status`] @@ -22,12 +40,12 @@ Timed wait-operations (__wait_for__ and __wait_until__) return the state of the [heading `ready`] [variablelist -[[Effects:] [The shared state is ready.]] +[[Effects:] [The [link shared_state shared state] is ready.]] ] [heading `timeout`] [variablelist -[[Effects:] [The shared state did not become ready before timeout has passed.]] +[[Effects:] [The [link shared_state shared state] did not become ready before timeout has passed.]] ] [heading `deferred`] @@ -41,7 +59,7 @@ Timed wait-operations (__wait_for__ and __wait_until__) return the state of the [template_heading future] -A __future__ contains a shared state which is not shared with any other future. +A __future__ contains a [link shared_state shared state] which is not shared with any other future. template< typename R > class future { @@ -62,68 +80,80 @@ A __future__ contains a shared state which is not shared with any other future. shared_future< R > share(); - R get(); // member only of generic future template - R & get(); // member only of future< R & > template specialization - void get(); // member only of future< void > template specialization + R get(); std::exception_ptr get_exception_ptr(); void wait() const; template< class Rep, class Period > - future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const; + future_status wait_for( + std::chrono::duration< Rep, Period > const& timeout_duration) const; template< typename Clock, typename Duration > - future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const; + future_status wait_until( + std::chrono::time_point< Clock, Duration > const& timeout_time) const; }; [heading Default constructor] future(); +[template future_ctor_variablelist[xfuture] [variablelist -[[Effects:] [Creates a future with no shared state. -After construction is `false == vaild()`.]] +[[Effects:] [Creates a [xfuture] with no [link shared_state shared state]. +After construction `false == valid()`.]] [[Throws:] [Nothing.]] ] +] +[future_ctor_variablelist future] [heading Move constructor] future( future && other) noexcept; +[template future_move_copy_ctor_variablelist[xfuture post_valid] [variablelist -[[Effects:] [Constructs a future with the shared state of other. -After construction is `false == other.valid()`]] +[[Effects:] [Constructs a [xfuture] with the [link shared_state shared state] of other. +After construction [^[post_valid] == other.valid()]]] [[Throws:] [Nothing.]] ] +] +[future_move_copy_ctor_variablelist future..false] [heading Destructor] ~future(); +[template future_dtor_variablelist[xfuture end] [variablelist -[[Effects:] [Destructs the future; ownership is abandoned.]] +[[Effects:] [Destroys the [xfuture]; ownership is abandoned[end]]] [[Throws:] [Nothing.]] ] +] +[future_dtor_variablelist future .] [operator_heading future..operator_assign..operator=] future & operator=( future && other) noexcept; [variablelist -[[Effects:] [Moves the shared state of other to `this`. -After construction is `false == other.valid()`]] +[[Effects:] [Moves the [link shared_state shared state] of other to `this`. +After the assignment, `false == other.valid()`.]] [[Throws:] [Nothing.]] ] -[member_heading future..valid] +[template future_valid[xfuture] +[member_heading [xfuture]..valid] bool valid() const noexcept; [variablelist -[[Effects:] [Returns `true` if future contains a shared state.]] +[[Effects:] [Returns `true` if [xfuture] contains a [link shared_state shared state].]] [[Throws:] [Nothing.]] ] +] +[future_valid future] [member_heading future..share] @@ -134,64 +164,78 @@ After construction is `false == other.valid()`]] [[Throws:] [__future_error__ with error condition __no_state__.]] ] +[template future_method_wait[end] Waits until [member_link promise..set_value] or +[member_link promise..set_exception] is called[end]] + [member_heading future..get] - R get(); // member only of generic future template - R & get(); // member only of future< R & > template specialization - void get(); // member only of future< void > template specialization + R get(); +[template future_get_variablelist[] [variablelist [[Precondition:] [`true == valid()`]] -[[Returns:] [the result. If result not yet set, waits.]] +[[Returns:] [[future_method_wait .] If `set_value()` is called, returns the +value. If `set_exception()` is called, throws the indicated exception.]] [[Postcondition:] [`false == valid()`]] -[[Throws:] [__future_error__ with error condition __no_state__ or __fiber_interrupted__.]] +[[Throws:] [__future_error__ with error condition __no_state__, or +__fiber_interrupted__. Any exception passed to `promise::set_exception()`.]] ] +] +[future_get_variablelist] -[member_heading future..get_exception_ptr] +[template future_get_exception_ptr[xfuture] +[member_heading [xfuture]..get_exception_ptr] std::exception_ptr get_exception_ptr(); [variablelist [[Precondition:] [`true == valid()`]] -[[Returns:] [the exception pointer, if set. If no result is set, waits.]] +[[Returns:] [[future_method_wait .] If `set_value()` is called, returns a +default-constructed `std::exception_ptr`. If `set_exception()` is called, +returns the passed `std::exception_ptr`.]] [[Throws:] [__future_error__ with error condition __no_state__ or __fiber_interrupted__.]] ] +] +[future_get_exception_ptr future] -[member_heading future..wait] +[template future_wait_etc[xfuture] +[member_heading [xfuture]..wait] void wait(); [variablelist -[[Effects:] [Waits for the result will become available.]] +[[Effects:] [[future_method_wait .]]] [[Throws:] [__future_error__ with error condition __no_state__ or __fiber_interrupted__.]] ] -[template_member_heading future..wait_for] +[template_member_heading [xfuture]..wait_for] template< class Rep, class Period > future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const; [variablelist -[[Effects:] [Waits for the result will become available or `timeout_duration` has passed.]] +[[Effects:] [[future_method_wait , or `timeout_duration` has passed.]]] [[Result:] [A `future_status` is returned indicating the reason for returning.]] [[Throws:] [__future_error__ with error condition __no_state__ or __fiber_interrupted__.]] ] -[member_heading future..wait_until] +[template_member_heading [xfuture]..wait_until] template< typename Clock, typename Duration > future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const; [variablelist -[[Effects:] [Waits for the result will become available or `timeout_time` has passed.]] +[[Effects:] [[future_method_wait , or `timeout_time` has passed.]]] [[Result:] [A `future_status` is returned indicating the reason for returning.]] [[Throws:] [__future_error__ with error condition __no_state__ or __fiber_interrupted__.]] ] +] +[future_wait_etc future] [template_heading shared_future] -A __shared_future__ contains a shared state which might be shared with other futures. +A __shared_future__ contains a [link shared_state shared state] which might be shared with other futures. template< typename R > class shared_future { @@ -218,6 +262,8 @@ A __shared_future__ contains a shared state which might be shared with other fut R & get(); // member only of shared_future< R & > template specialization void get(); // member only of shared_future< void > template specialization + std::exception_ptr get_exception_ptr(); + void wait() const; template< class Rep, class Period > @@ -231,41 +277,26 @@ A __shared_future__ contains a shared state which might be shared with other fut shared_future(); -[variablelist -[[Effects:] [Creates a future with no shared state. -After construction is `false == vaild()`.]] -[[Throws:] [Nothing.]] -] +[future_ctor_variablelist shared_future] [heading Move constructor] shared_future( future && other) noexcept; shared_future( shared_future && other) noexcept; -[variablelist -[[Effects:] [Constructs a future with the shared state of other. -After construction is `false == other.valid()`.]] -[[Throws:] [Nothing.]] -] +[future_move_copy_ctor_variablelist shared_future..false] [heading Copy constructor] shared_future( shared_future const& other) noexcept; -[variablelist -[[Effects:] [Constructs a future with the shared state of other. -After construction is `true == other.valid()`.]] -[[Throws:] [Nothing.]] -] +[future_move_copy_ctor_variablelist shared_future..true] [heading Destructor] ~shared_future(); -[variablelist -[[Effects:] [Destructs the future; ownership is abandoned if not shared.]] -[[Throws:] [Nothing.]] -] +[future_dtor_variablelist shared_future.. if not shared.] [operator_heading shared_future..operator_assign..operator=] @@ -274,23 +305,14 @@ After construction is `true == other.valid()`.]] shared_future & operator=( shared_future const& other) noexcept; [variablelist -[[Effects:] [Transfers the ownership of shared state according to: `` -shared_future tmp( other); -swap( tmp); -return * this; -`` -]] +[[Effects:] [Moves or copies the [link shared_state shared state] of other to +`this`. After the assignment, the state of `other.valid()` depends on which +overload was invoked: `true` for the overload accepting `shared_future +const&`, otherwise `false`.]] [[Throws:] [Nothing.]] ] -[member_heading shared_future..valid] - - bool valid() const noexcept; - -[variablelist -[[Effects:] [Returns `true` if future contains a shared state.]] -[[Throws:] [Nothing.]] -] +[future_valid shared_future] [member_heading shared_future..get] @@ -298,69 +320,33 @@ return * this; R & get(); // member only of shared_future< R & > template specialization void get(); // member only of shared_future< void > template specialization -[variablelist -[[Precondition:] [`true == valid()`]] -[[Effects:] [Returns the result.]] -[[Postcondition:] [`false == valid()`]] -[[Throws:] [__future_error__ with error condition __no_state__ or __fiber_interrupted__.]] -] +[future_get_variablelist] -[member_heading shared_future..get_exception_ptr] +[future_get_exception_ptr shared_future] - std::exception_ptr get_exception_ptr(); - -[variablelist -[[Precondition:] [`true == valid()`]] -[[Returns:] [the exception pointer, if set. If no result is set, waits.]] -[[Throws:] [__future_error__ with error condition __no_state__ or __fiber_interrupted__.]] -] - -[member_heading shared_future..wait] - - void wait(); - -[variablelist -[[Effects:] [Waits for the result will become available.]] -[[Throws:] [__future_error__ with error condition __no_state__ or __fiber_interrupted__.]] -] - -[template_member_heading shared_future..wait_for] - - template< class Rep, class Period > - future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const; - -[variablelist -[[Effects:] [Waits for the result will become available or `timeout_duration` has passed.]] -[[Result:] [A `future_status` is returned indicating the reason for returning.]] -[[Throws:] [__future_error__ with error condition __no_state__ or __fiber_interrupted__.]] -] - -[member_heading shared_future..wait_until] - - template< typename Clock, typename Duration > - future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const; - -[variablelist -[[Effects:] [Waits for the result will become available or `timeout_time` has passed.]] -[[Result:] [A `future_status` is returned indicating the reason for returning.]] -[[Throws:] [__future_error__ with error condition __no_state__ or __fiber_interrupted__.]] -] -] +[future_wait_etc shared_future] [ns_function_heading fibers..async] #include - template< typename Fn > - future< typename result_of< Fn >::type > async( Fn && fn); + template< typename Fn, typename ... Args > + future< typename result_of< Fn&&( Args && ... ) >::type > + async( Fn && fn, Args && ... args); + + template< typename StackAllocator, typename Fn, typename ... Args > + future< typename result_of< Fn&&( Args && ... ) >::type > + async( std::allocator_arg_t, StackAllocator salloc, Fn && fn, Args && ... args); [variablelist -[[Effects:] [Executes `fn` in a fiber and returns an associated future.]] -[[Result:] [`future< typename result_of< Fn >::type >` representing the shared state associated with -the asynchronous execution of `fn`.]] +[[Effects:] [Executes `fn` in a [class_link fiber] and returns an associated +[template_link future].]] +[[Result:] [`future< typename result_of< Fn >::type >` representing the [link +shared_state shared state] associated with the asynchronous execution of +`fn`.]] [[Throws:] [__fiber_exception__ or __future_error__ if an error occurs.]] +[[Notes:] [The overload accepting `std::allocator_arg_t` uses the passed +`StackAllocator` when constructing the launched `fiber`.]] ] -[warning Launch policy `deferred`, which indicates you simply want to defer the function call until a later time (lazy evaluation), is not supported yet.] - [endsect] diff --git a/doc/futures.qbk b/doc/futures.qbk index 9c9af64e..39f87a24 100644 --- a/doc/futures.qbk +++ b/doc/futures.qbk @@ -33,7 +33,8 @@ __shared_future__, thus transferring ownership of the associated asynchronous result, but not vice-versa. __async__ is a simple way of running asynchronous tasks. A call to __async__ -returns a __future__ that will deliver the result of the task. +spawns a fiber and returns a __future__ that will deliver the result of the +fiber function. [heading Creating asynchronous values] diff --git a/doc/packaged_task.qbk b/doc/packaged_task.qbk index 7012fc11..9fab07aa 100644 --- a/doc/packaged_task.qbk +++ b/doc/packaged_task.qbk @@ -52,7 +52,7 @@ return value can be computed asynchronously. packaged_task(); [variablelist -[[Effects:] [Constructs an object of class `packaged_task` with no shared state.]] +[[Effects:] [Constructs an object of class `packaged_task` with no [link shared_state shared state].]] [[Throws:] [Nothing.]] ] @@ -65,7 +65,7 @@ return value can be computed asynchronously. explicit packaged_task( std::allocator_arg_t, Allocator const& alloc, Fn && fn); [variablelist -[[Effects:] [Constructs an object of class `packaged_task` with a shared state +[[Effects:] [Constructs an object of class `packaged_task` with a [link shared_state shared state] and stores the callable target `fn` internally.]] [[Throws:] [Nothing.]] [[Note:] [The signature of `Fn` should have a return type convertible to `R`.]] @@ -76,7 +76,7 @@ and stores the callable target `fn` internally.]] packaged_task( packaged_task && other) noexcept; [variablelist -[[Effects:] [Creates a packaged_task by moving the shared state from `other`.]] +[[Effects:] [Creates a packaged_task by moving the [link shared_state shared state] from `other`.]] [[Postcondition:] [`other` contains no valid shared state.]] [[Throws:] [Nothing.]] ] @@ -86,7 +86,7 @@ and stores the callable target `fn` internally.]] ~packaged_task(); [variablelist -[[Effects:] [Destroys `*this` and abandons the shared state if shared state is +[[Effects:] [Destroys `*this` and abandons the [link shared_state shared state] if shared state is ready; otherwise stores __future_error__ with error condition __broken_promise__.]] [[Throws:] [Nothing.]] ] @@ -96,7 +96,7 @@ ready; otherwise stores __future_error__ with error condition __broken_promise__ packaged_task & operator=( packaged_task && other) noexcept; [variablelist -[[Effects:] [Transfers the ownership of shared state to `*this`.]] +[[Effects:] [Transfers the ownership of [link shared_state shared state] to `*this`.]] [[Postcondition:] [`other` contains no valid shared state.]] [[Throws:] [Nothing.]] ] @@ -106,7 +106,7 @@ ready; otherwise stores __future_error__ with error condition __broken_promise__ void swap( packaged_task & other) noexcept; [variablelist -[[Effects:] [Swaps the shared state between other and `*this`.]] +[[Effects:] [Swaps the [link shared_state shared state] between other and `*this`.]] [[Throws:] [Nothing.]] ] @@ -115,7 +115,7 @@ ready; otherwise stores __future_error__ with error condition __broken_promise__ operator safe_bool() const noexcept; [variablelist -[[Effects:] [Returns `true` if `*this` contains a non-empty shared state.]] +[[Effects:] [Returns `true` if `*this` contains a non-empty [link shared_state shared state].]] [[Throws:] [Nothing.]] ] @@ -124,7 +124,7 @@ ready; otherwise stores __future_error__ with error condition __broken_promise__ bool operator!() const noexcept; [variablelist -[[Effects:] [Returns `true` if `*this` contains an empty shared state.]] +[[Effects:] [Returns `true` if `*this` contains an empty [link shared_state shared state].]] [[Throws:] [Nothing.]] ] @@ -133,7 +133,7 @@ ready; otherwise stores __future_error__ with error condition __broken_promise__ bool valid() const noexcept; [variablelist -[[Effects:] [Returns `true` if `*this` contains a shared state.]] +[[Effects:] [Returns `true` if `*this` contains a [link shared_state shared state].]] [[Throws:] [Nothing.]] ] @@ -142,7 +142,7 @@ ready; otherwise stores __future_error__ with error condition __broken_promise__ future< R > get_future(); [variablelist -[[Returns:] [A __future__ with the same shared state.]] +[[Returns:] [A __future__ with the same [link shared_state shared state].]] [[Throws:] [__future_error__ with __already_retrieved__ or __no_state__.]] ] @@ -152,7 +152,7 @@ ready; otherwise stores __future_error__ with error condition __broken_promise__ [variablelist [[Effects:] [Invokes the stored callable target. Any exception thrown by the -callable target `fn` is stored in the shared state. Otherwise, the value returned +callable target `fn` is stored in the [link shared_state shared state]. Otherwise, the value returned by `fn` is stored in the shared state.]] [[Throws:] [__future_error__ with __no_state__.]] ] @@ -162,7 +162,7 @@ by `fn` is stored in the shared state.]] void reset(); [variablelist -[[Effects:] [Resets the shared state and abondons the result of previous +[[Effects:] [Resets the [link shared_state shared state] and abondons the result of previous executions. A new shared state is constructed.]] [[Throws:] [__future_error__ with __no_state__.]] ] diff --git a/doc/promise.qbk b/doc/promise.qbk index 53065e7e..8dea1d94 100644 --- a/doc/promise.qbk +++ b/doc/promise.qbk @@ -8,8 +8,9 @@ [#class_promise] [section:promise Template `promise<>`] -A __promise__ provides a mechanism to store a value that can later be accessed -asynchronously by a __future__ object. +A __promise__ provides a mechanism to store a value (or exception) that can +later be retrieved from the corresponding __future__ object. `promise<>` and +`future<>` communicate via their underlying [link shared_state shared state]. template< typename R > class promise { @@ -31,17 +32,13 @@ asynchronously by a __future__ object. void swap( promise & other) noexcept; - operator safe_bool() const noexcept; - - bool operator!() const noexcept; - future< R > get_future(); void set_value( R const& value); void set_value( R && value); - void set_exception( exception_ptr p); + void set_exception( std::exception_ptr p); }; [heading Default constructor] @@ -49,7 +46,7 @@ asynchronously by a __future__ object. promise(); [variablelist -[[Effects:] [Creates a promise with an empty shared state.]] +[[Effects:] [Creates a promise with an empty [link shared_state shared state].]] [[Throws:] [Nothing.]] ] @@ -59,7 +56,7 @@ asynchronously by a __future__ object. promise( std::allocator_arg_t, Allocator alloc); [variablelist -[[Effects:] [Creates a promise with an empty shared state by using `alloc`.]] +[[Effects:] [Creates a promise with an empty [link shared_state shared state] by using `alloc`.]] [[Throws:] [Nothing.]] ] @@ -68,7 +65,7 @@ asynchronously by a __future__ object. promise( promise && other) noexcept; [variablelist -[[Effects:] [Creates a promise by moving the shared state from `other`.]] +[[Effects:] [Creates a promise by moving the [link shared_state shared state] from `other`.]] [[Postcondition:] [`other` contains no valid shared state.]] [[Throws:] [Nothing.]] ] @@ -78,7 +75,7 @@ asynchronously by a __future__ object. ~promise(); [variablelist -[[Effects:] [Destroys `*this` and abandons the shared state if shared state is +[[Effects:] [Destroys `*this` and abandons the [link shared_state shared state] if shared state is ready; otherwise stores __future_error__ with error condition __broken_promise__.]] [[Throws:] [Nothing.]] ] @@ -88,7 +85,7 @@ ready; otherwise stores __future_error__ with error condition __broken_promise__ promise & operator=( promise && other) noexcept; [variablelist -[[Effects:] [Transfers the ownership of shared state to `*this`.]] +[[Effects:] [Transfers the ownership of [link shared_state shared state] to `*this`.]] [[Postcondition:] [`other` contains no valid shared state.]] [[Throws:] [Nothing.]] ] @@ -98,25 +95,7 @@ ready; otherwise stores __future_error__ with error condition __broken_promise__ void swap( promise & other) noexcept; [variablelist -[[Effects:] [Swaps the shared state between other and `*this`.]] -[[Throws:] [Nothing.]] -] - -[member_heading promise..operator safe_bool] - - operator safe_bool() const noexcept; - -[variablelist -[[Effects:] [Returns `true` if `*this` contains a non-empty shared state.]] -[[Throws:] [Nothing.]] -] - -[operator_heading promise..operator_not..operator!] - - bool operator!() const noexcept; - -[variablelist -[[Effects:] [Returns `true` if `*this` contains an empty shared state.]] +[[Effects:] [Swaps the [link shared_state shared state] between other and `*this`.]] [[Throws:] [Nothing.]] ] @@ -125,7 +104,7 @@ ready; otherwise stores __future_error__ with error condition __broken_promise__ future< R > get_future(); [variablelist -[[Returns:] [A __future__ with the same shared state.]] +[[Returns:] [A __future__ with the same [link shared_state shared state].]] [[Throws:] [__future_error__ with __already_retrieved__ or __no_state__.]] ] @@ -135,16 +114,16 @@ ready; otherwise stores __future_error__ with error condition __broken_promise__ void set_value( R && value); [variablelist -[[Effects:] [Store the result in the shared state and marks the state as ready.]] +[[Effects:] [Store the result in the [link shared_state shared state] and marks the state as ready.]] [[Throws:] [__future_error__ with __already_satisfied__ or __no_state__.]] ] [member_heading promise..set_exception] - void set_exception( exception_ptr); + void set_exception( std::exception_ptr); [variablelist -[[Effects:] [Store an exception pointer in the shared state and marks the state as ready.]] +[[Effects:] [Store an exception pointer in the [link shared_state shared state] and marks the state as ready.]] [[Throws:] [__future_error__ with __already_satisfied__ or __no_state__.]] ]