1[/ 2 Copyright Oliver Kowalke 2013. 3 Distributed under the Boost Software License, Version 1.0. 4 (See accompanying file LICENSE_1_0.txt or copy at 5 http://www.boost.org/LICENSE_1_0.txt 6] 7 8[section:future Future] 9 10A future provides a mechanism to access the result of an asynchronous operation. 11 12[#shared_state] 13[heading shared state] 14 15Behind a [template_link promise] and its [template_link future] lies an 16unspecified object called their ['shared state]. The shared state is what will 17actually hold the async result (or the exception). 18 19The shared state is instantiated along with the [template_link promise]. 20 21Aside from its originating `promise<>`, a [template_link future] holds a 22unique reference to a particular shared state. However, multiple 23[template_link shared_future] instances can reference the same underlying 24shared state. 25 26As [template_link packaged_task] and [ns_function_link fibers..async] are 27implemented using [template_link promise], discussions of shared state apply 28to them as well. 29 30[#class_future_status] 31[heading Enumeration `future_status`] 32 33Timed wait-operations (__wait_for__ and __wait_until__) return the state of the future. 34 35 enum class future_status { 36 ready, 37 timeout, 38 deferred // not supported yet 39 }; 40 41[heading `ready`] 42[variablelist 43[[Effects:] [The [link shared_state shared state] is ready.]] 44] 45 46[heading `timeout`] 47[variablelist 48[[Effects:] [The [link shared_state shared state] did not become ready before timeout has passed.]] 49] 50 51[note Deferred futures are not supported.] 52 53 54[template_heading future] 55 56A __future__ contains a [link shared_state shared state] which is not shared with any other future. 57 58 #include <boost/fiber/future/future.hpp> 59 60 namespace boost { 61 namespace fibers { 62 63 template< typename R > 64 class future { 65 public: 66 future() noexcept; 67 68 future( future const& other) = delete; 69 70 future & operator=( future const& other) = delete; 71 72 future( future && other) noexcept; 73 74 future & operator=( future && other) noexcept; 75 76 ~future(); 77 78 bool valid() const noexcept; 79 80 shared_future< R > share(); 81 82 R get(); // member only of generic future template 83 R & get(); // member only of future< R & > template specialization 84 void get(); // member only of future< void > template specialization 85 86 std::exception_ptr get_exception_ptr(); 87 88 void wait() const; 89 90 template< class Rep, class Period > 91 future_status wait_for( 92 std::chrono::duration< Rep, Period > const& timeout_duration) const; 93 94 template< typename Clock, typename Duration > 95 future_status wait_until( 96 std::chrono::time_point< Clock, Duration > const& timeout_time) const; 97 }; 98 99 }} 100 101[heading Default constructor] 102 103 future() noexcept; 104 105[template future_ctor_variablelist[xfuture] 106[variablelist 107[[Effects:] [Creates a [xfuture] with no [link shared_state shared state]. 108After construction `false == valid()`.]] 109[[Throws:] [Nothing.]] 110] 111] 112[future_ctor_variablelist future] 113 114[heading Move constructor] 115 116 future( future && other) noexcept; 117 118[template future_move_copy_ctor_variablelist[xfuture post_valid] 119[variablelist 120[[Effects:] [Constructs a [xfuture] with the [link shared_state shared state] of other. 121After construction [post_valid].]] 122[[Throws:] [Nothing.]] 123] 124] 125[future_move_copy_ctor_variablelist future..`false == other.valid()`] 126 127[heading Destructor] 128 129 ~future(); 130 131[template future_dtor_variablelist[xfuture end] 132[variablelist 133[[Effects:] [Destroys the [xfuture]; ownership is abandoned[end]]] 134[[Note:] [[`~[xfuture]()] does ['not] block the calling fiber.]] 135] 136] 137[future_dtor_variablelist future .] 138 139Consider a sequence such as: 140 141# instantiate [template_link promise] 142# obtain its `future<>` via [member_link promise..get_future] 143# launch [class_link fiber], capturing `promise<>` 144# destroy `future<>` 145# call [member_link promise..set_value] 146 147The final `set_value()` call succeeds, but the value is silently discarded: no 148additional `future<>` can be obtained from that `promise<>`. 149 150[operator_heading future..operator_assign..operator=] 151 152 future & operator=( future && other) noexcept; 153 154[variablelist 155[[Effects:] [Moves the [link shared_state shared state] of other to `this`. 156After the assignment, `false == other.valid()`.]] 157[[Throws:] [Nothing.]] 158] 159 160[template future_valid[xfuture] 161[member_heading [xfuture]..valid] 162 163 bool valid() const noexcept; 164 165[variablelist 166[[Effects:] [Returns `true` if [xfuture] contains a [link shared_state shared state].]] 167[[Throws:] [Nothing.]] 168] 169] 170[future_valid future] 171 172[member_heading future..share] 173 174 shared_future< R > share(); 175 176[variablelist 177[[Effects:] [Move the state to a __shared_future__.]] 178[[Returns:] [a __shared_future__ containing the [link shared_state shared 179state] formerly belonging to `*this`.]] 180[[Postcondition:] [`false == valid()`]] 181[[Throws:] [__future_error__ with error condition __no_state__.]] 182] 183 184[template future_method_wait[end] Waits until [member_link promise..set_value] or 185[member_link promise..set_exception] is called[end]] 186 187[member_heading future..get] 188 189 R get(); // member only of generic future template 190 R & get(); // member only of future< R & > template specialization 191 void get(); // member only of future< void > template specialization 192 193[template future_get_variablelist[] 194[variablelist 195[[Precondition:] [`true == valid()`]] 196[[Returns:] [[future_method_wait .] If [member_link promise..set_value] is 197called, returns the value. If [member_link promise..set_exception] is called, 198throws the indicated exception.]] 199[[Postcondition:] [`false == valid()`]] 200[[Throws:] [__future_error__ with error condition __no_state__, 201__broken_promise__. Any exception passed to 202`promise::set_exception()`.]] 203] 204] 205[future_get_variablelist] 206 207[template future_get_exception_ptr[xfuture] 208[member_heading [xfuture]..get_exception_ptr] 209 210 std::exception_ptr get_exception_ptr(); 211 212[variablelist 213[[Precondition:] [`true == valid()`]] 214[[Returns:] [[future_method_wait .] If `set_value()` is called, returns a 215default-constructed `std::exception_ptr`. If `set_exception()` is called, 216returns the passed `std::exception_ptr`.]] 217[[Throws:] [__future_error__ with error condition __no_state__.]] 218[[Note:] [ `get_exception_ptr()` does ['not] invalidate the [`[xfuture]]. 219After calling `get_exception_ptr()`, you may still call [member_link 220[xfuture]..get].]] 221] 222] 223[future_get_exception_ptr future] 224 225[template future_wait_etc[xfuture] 226[member_heading [xfuture]..wait] 227 228 void wait(); 229 230[variablelist 231[[Effects:] [[future_method_wait .]]] 232[[Throws:] [__future_error__ with error condition __no_state__.]] 233] 234 235[template_member_heading [xfuture]..wait_for] 236 237 template< class Rep, class Period > 238 future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const; 239 240[variablelist 241[[Effects:] [[future_method_wait , or `timeout_duration` has passed.]]] 242[[Result:] [A `future_status` is returned indicating the reason for returning.]] 243[[Throws:] [__future_error__ with error condition __no_state__ or 244timeout-related exceptions.]] 245] 246 247[template_member_heading [xfuture]..wait_until] 248 249 template< typename Clock, typename Duration > 250 future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const; 251 252[variablelist 253[[Effects:] [[future_method_wait , or `timeout_time` has passed.]]] 254[[Result:] [A `future_status` is returned indicating the reason for returning.]] 255[[Throws:] [__future_error__ with error condition __no_state__ or 256timeout-related exceptions.]] 257] 258] 259[future_wait_etc future] 260 261 262[template_heading shared_future] 263 264A __shared_future__ contains a [link shared_state shared state] which might be 265shared with other __shared_future__ instances. 266 267 #include <boost/fiber/future/future.hpp> 268 269 namespace boost { 270 namespace fibers { 271 272 template< typename R > 273 class shared_future { 274 public: 275 shared_future() noexcept; 276 277 ~shared_future(); 278 279 shared_future( shared_future const& other); 280 281 shared_future( future< R > && other) noexcept; 282 283 shared_future( shared_future && other) noexcept; 284 285 shared_future & operator=( shared_future && other) noexcept; 286 287 shared_future & operator=( future< R > && other) noexcept; 288 289 shared_future & operator=( shared_future const& other) noexcept; 290 291 bool valid() const noexcept; 292 293 R const& get(); // member only of generic shared_future template 294 R & get(); // member only of shared_future< R & > template specialization 295 void get(); // member only of shared_future< void > template specialization 296 297 std::exception_ptr get_exception_ptr(); 298 299 void wait() const; 300 301 template< class Rep, class Period > 302 future_status wait_for( 303 std::chrono::duration< Rep, Period > const& timeout_duration) const; 304 305 template< typename Clock, typename Duration > 306 future_status wait_until( 307 std::chrono::time_point< Clock, Duration > const& timeout_time) const; 308 }; 309 310 }} 311 312[heading Default constructor] 313 314 shared_future(); 315 316[future_ctor_variablelist shared_future] 317 318[heading Move constructor] 319 320 shared_future( future< R > && other) noexcept; 321 shared_future( shared_future && other) noexcept; 322 323[future_move_copy_ctor_variablelist shared_future..`false == other.valid()`] 324 325[heading Copy constructor] 326 327 shared_future( shared_future const& other) noexcept; 328 329[future_move_copy_ctor_variablelist shared_future..`other.valid()` is unchanged] 330 331[heading Destructor] 332 333 ~shared_future(); 334 335[future_dtor_variablelist shared_future.. if not shared.] 336 337[operator_heading shared_future..operator_assign..operator=] 338 339 shared_future & operator=( future< R > && other) noexcept; 340 shared_future & operator=( shared_future && other) noexcept; 341 shared_future & operator=( shared_future const& other) noexcept; 342 343[variablelist 344[[Effects:] [Moves or copies the [link shared_state shared state] of other to 345`this`. After the assignment, the state of `other.valid()` depends on which 346overload was invoked: unchanged for the overload accepting `shared_future 347const&`, otherwise `false`.]] 348[[Throws:] [Nothing.]] 349] 350 351[future_valid shared_future] 352 353[member_heading shared_future..get] 354 355 R const& get(); // member only of generic shared_future template 356 R & get(); // member only of shared_future< R & > template specialization 357 void get(); // member only of shared_future< void > template specialization 358 359[future_get_variablelist] 360 361[future_get_exception_ptr shared_future] 362 363[future_wait_etc shared_future] 364 365[ns_function_heading fibers..async] 366 367 #include <boost/fiber/future/async.hpp> 368 369 namespace boost { 370 namespace fibers { 371 372 template< class Function, class ... Args > 373 future< 374 std::result_of_t< 375 std::decay_t< Function >( std::decay_t< Args > ... ) 376 > 377 > 378 async( Function && fn, Args && ... args); 379 380 template< class Function, class ... Args > 381 future< 382 std::result_of_t< 383 std::decay_t< Function >( std::decay_t< Args > ... ) 384 > 385 > 386 async( ``[link class_launch `launch`]`` policy, Function && fn, Args && ... args); 387 388 template< typename __StackAllocator__, class Function, class ... Args > 389 future< 390 std::result_of_t< 391 std::decay_t< Function >( std::decay_t< Args > ... ) 392 > 393 > 394 async( ``[link class_launch `launch`]`` policy, __allocator_arg_t__, __StackAllocator__ salloc, 395 Function && fn, Args && ... args); 396 397 template< typename __StackAllocator__, typename Allocator, class Function, class ... Args > 398 future< 399 std::result_of_t< 400 std::decay_t< Function >( std::decay_t< Args > ... ) 401 > 402 > 403 async( ``[link class_launch `launch`]`` policy, __allocator_arg_t__, __StackAllocator__ salloc, 404 Allocator alloc, Function && fn, Args && ... args); 405 406 }} 407 408[variablelist 409[[Effects:] [Executes `fn` in a [class_link fiber] and returns an associated 410[template_link future].]] 411[[Result:] [``future< 412 std::result_of_t< 413 std::decay_t< Function >( std::decay_t< Args > ... ) 414 > 415>`` representing the [link 416shared_state shared state] associated with the asynchronous execution of 417`fn`.]] 418[[Throws:] [__fiber_error__ or __future_error__ if an error occurs.]] 419[[Notes:] [The overloads accepting __allocator_arg_t__ use the passed 420__StackAllocator__ when constructing the launched `fiber`. The overloads 421accepting [class_link launch] use the passed `launch` when 422constructing the launched `fiber`. The default `launch` is `post`, as 423for the `fiber` constructor.]] 424] 425 426[note Deferred futures are not supported.] 427 428[endsect] 429