File indexing completed on 2025-01-30 09:35:35
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_FIBERS_FUTURE_HPP
0008 #define BOOST_FIBERS_FUTURE_HPP
0009
0010 #include <algorithm>
0011 #include <chrono>
0012 #include <exception>
0013 #include <utility>
0014
0015 #include <boost/config.hpp>
0016
0017 #include <boost/fiber/detail/config.hpp>
0018 #include <boost/fiber/exceptions.hpp>
0019 #include <boost/fiber/future/detail/shared_state.hpp>
0020 #include <boost/fiber/future/future_status.hpp>
0021
0022 namespace boost {
0023 namespace fibers {
0024 namespace detail {
0025
0026 template< typename R >
0027 struct future_base {
0028 typedef typename shared_state< R >::ptr_type ptr_type;
0029
0030 ptr_type state_{};
0031
0032 future_base() = default;
0033
0034 explicit future_base( ptr_type p) noexcept :
0035 state_{std::move( p )} {
0036 }
0037
0038 ~future_base() = default;
0039
0040 future_base( future_base const& other) :
0041 state_{ other.state_ } {
0042 }
0043
0044 future_base( future_base && other) noexcept :
0045 state_{ other.state_ } {
0046 other.state_.reset();
0047 }
0048
0049 future_base & operator=( future_base const& other) noexcept {
0050 if ( BOOST_LIKELY( this != & other) ) {
0051 state_ = other.state_;
0052 }
0053 return * this;
0054 }
0055
0056 future_base & operator=( future_base && other) noexcept {
0057 if ( BOOST_LIKELY( this != & other) ) {
0058 state_ = other.state_;
0059 other.state_.reset();
0060 }
0061 return * this;
0062 }
0063
0064 bool valid() const noexcept {
0065 return nullptr != state_.get();
0066 }
0067
0068 std::exception_ptr get_exception_ptr() {
0069 if ( BOOST_UNLIKELY( ! valid() ) ) {
0070 throw future_uninitialized{};
0071 }
0072 return state_->get_exception_ptr();
0073 }
0074
0075 void wait() const {
0076 if ( BOOST_UNLIKELY( ! valid() ) ) {
0077 throw future_uninitialized{};
0078 }
0079 state_->wait();
0080 }
0081
0082 template< typename Rep, typename Period >
0083 future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
0084 if ( BOOST_UNLIKELY( ! valid() ) ) {
0085 throw future_uninitialized{};
0086 }
0087 return state_->wait_for( timeout_duration);
0088 }
0089
0090 template< typename Clock, typename Duration >
0091 future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
0092 if ( BOOST_UNLIKELY( ! valid() ) ) {
0093 throw future_uninitialized{};
0094 }
0095 return state_->wait_until( timeout_time);
0096 }
0097 };
0098
0099 template< typename R >
0100 struct promise_base;
0101
0102 }
0103
0104 template< typename R >
0105 class shared_future;
0106
0107 template< typename Signature >
0108 class packaged_task;
0109
0110 template< typename R >
0111 class future : private detail::future_base< R > {
0112 private:
0113 typedef detail::future_base< R > base_type;
0114
0115 friend struct detail::promise_base< R >;
0116 friend class shared_future< R >;
0117 template< typename Signature >
0118 friend class packaged_task;
0119
0120 explicit future( typename base_type::ptr_type const& p) noexcept :
0121 base_type{ p } {
0122 }
0123
0124 public:
0125 future() = default;
0126
0127 future( future const&) = delete;
0128 future & operator=( future const&) = delete;
0129
0130 future( future && other) noexcept :
0131 base_type{ std::move( other) } {
0132 }
0133
0134 future & operator=( future && other) noexcept {
0135 if ( BOOST_LIKELY( this != & other) ) {
0136 base_type::operator=( std::move( other) );
0137 }
0138 return * this;
0139 }
0140
0141 shared_future< R > share();
0142
0143 R get() {
0144 if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
0145 throw future_uninitialized{};
0146 }
0147 typename base_type::ptr_type tmp{};
0148 tmp.swap( base_type::state_);
0149 return std::move( tmp->get() );
0150 }
0151
0152 using base_type::valid;
0153 using base_type::get_exception_ptr;
0154 using base_type::wait;
0155 using base_type::wait_for;
0156 using base_type::wait_until;
0157 };
0158
0159 template< typename R >
0160 class future< R & > : private detail::future_base< R & > {
0161 private:
0162 typedef detail::future_base< R & > base_type;
0163
0164 friend struct detail::promise_base< R & >;
0165 friend class shared_future< R & >;
0166 template< typename Signature >
0167 friend class packaged_task;
0168
0169 explicit future( typename base_type::ptr_type const& p) noexcept :
0170 base_type{ p } {
0171 }
0172
0173 public:
0174 future() = default;
0175
0176 future( future const&) = delete;
0177 future & operator=( future const&) = delete;
0178
0179 future( future && other) noexcept :
0180 base_type{ std::move( other) } {
0181 }
0182
0183 future & operator=( future && other) noexcept {
0184 if ( BOOST_LIKELY( this != & other) ) {
0185 base_type::operator=( std::move( other) );
0186 }
0187 return * this;
0188 }
0189
0190 shared_future< R & > share();
0191
0192 R & get() {
0193 if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
0194 throw future_uninitialized{};
0195 }
0196 typename base_type::ptr_type tmp{};
0197 tmp.swap( base_type::state_);
0198 return tmp->get();
0199 }
0200
0201 using base_type::valid;
0202 using base_type::get_exception_ptr;
0203 using base_type::wait;
0204 using base_type::wait_for;
0205 using base_type::wait_until;
0206 };
0207
0208 template<>
0209 class future< void > : private detail::future_base< void > {
0210 private:
0211 typedef detail::future_base< void > base_type;
0212
0213 friend struct detail::promise_base< void >;
0214 friend class shared_future< void >;
0215 template< typename Signature >
0216 friend class packaged_task;
0217
0218 explicit future( base_type::ptr_type const& p) noexcept :
0219 base_type{ p } {
0220 }
0221
0222 public:
0223 future() = default;
0224
0225 future( future const&) = delete;
0226 future & operator=( future const&) = delete;
0227
0228 inline
0229 future( future && other) noexcept :
0230 base_type{ std::move( other) } {
0231 }
0232
0233 inline
0234 future & operator=( future && other) noexcept {
0235 if ( BOOST_LIKELY( this != & other) ) {
0236 base_type::operator=( std::move( other) );
0237 }
0238 return * this;
0239 }
0240
0241 shared_future< void > share();
0242
0243 inline
0244 void get() {
0245 if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
0246 throw future_uninitialized{};
0247 }
0248 base_type::ptr_type tmp{};
0249 tmp.swap( base_type::state_);
0250 tmp->get();
0251 }
0252
0253 using base_type::valid;
0254 using base_type::get_exception_ptr;
0255 using base_type::wait;
0256 using base_type::wait_for;
0257 using base_type::wait_until;
0258 };
0259
0260
0261 template< typename R >
0262 class shared_future : private detail::future_base< R > {
0263 private:
0264 typedef detail::future_base< R > base_type;
0265
0266 explicit shared_future( typename base_type::ptr_type const& p) noexcept :
0267 base_type{ p } {
0268 }
0269
0270 public:
0271 shared_future() = default;
0272
0273 ~shared_future() = default;
0274
0275 shared_future( shared_future const& other) :
0276 base_type{ other } {
0277 }
0278
0279 shared_future( shared_future && other) noexcept :
0280 base_type{ std::move( other) } {
0281 }
0282
0283 shared_future( future< R > && other) noexcept :
0284 base_type{ std::move( other) } {
0285 }
0286
0287 shared_future & operator=( shared_future const& other) noexcept {
0288 if ( BOOST_LIKELY( this != & other) ) {
0289 base_type::operator=( other);
0290 }
0291 return * this;
0292 }
0293
0294 shared_future & operator=( shared_future && other) noexcept {
0295 if ( BOOST_LIKELY( this != & other) ) {
0296 base_type::operator=( std::move( other) );
0297 }
0298 return * this;
0299 }
0300
0301 shared_future & operator=( future< R > && other) noexcept {
0302 base_type::operator=( std::move( other) );
0303 return * this;
0304 }
0305
0306 R const& get() const {
0307 if ( BOOST_UNLIKELY( ! valid() ) ) {
0308 throw future_uninitialized{};
0309 }
0310 return base_type::state_->get();
0311 }
0312
0313 using base_type::valid;
0314 using base_type::get_exception_ptr;
0315 using base_type::wait;
0316 using base_type::wait_for;
0317 using base_type::wait_until;
0318 };
0319
0320 template< typename R >
0321 class shared_future< R & > : private detail::future_base< R & > {
0322 private:
0323 typedef detail::future_base< R & > base_type;
0324
0325 explicit shared_future( typename base_type::ptr_type const& p) noexcept :
0326 base_type{ p } {
0327 }
0328
0329 public:
0330 shared_future() = default;
0331
0332 ~shared_future() = default;
0333
0334 shared_future( shared_future const& other) :
0335 base_type{ other } {
0336 }
0337
0338 shared_future( shared_future && other) noexcept :
0339 base_type{ std::move( other) } {
0340 }
0341
0342 shared_future( future< R & > && other) noexcept :
0343 base_type{ std::move( other) } {
0344 }
0345
0346 shared_future & operator=( shared_future const& other) noexcept {
0347 if ( BOOST_LIKELY( this != & other) ) {
0348 base_type::operator=( other);
0349 }
0350 return * this;
0351 }
0352
0353 shared_future & operator=( shared_future && other) noexcept {
0354 if ( BOOST_LIKELY( this != & other) ) {
0355 base_type::operator=( std::move( other) );
0356 }
0357 return * this;
0358 }
0359
0360 shared_future & operator=( future< R & > && other) noexcept {
0361 base_type::operator=( std::move( other) );
0362 return * this;
0363 }
0364
0365 R & get() const {
0366 if ( BOOST_UNLIKELY( ! valid() ) ) {
0367 throw future_uninitialized{};
0368 }
0369 return base_type::state_->get();
0370 }
0371
0372 using base_type::valid;
0373 using base_type::get_exception_ptr;
0374 using base_type::wait;
0375 using base_type::wait_for;
0376 using base_type::wait_until;
0377 };
0378
0379 template<>
0380 class shared_future< void > : private detail::future_base< void > {
0381 private:
0382 typedef detail::future_base< void > base_type;
0383
0384 explicit shared_future( base_type::ptr_type const& p) noexcept :
0385 base_type{ p } {
0386 }
0387
0388 public:
0389 shared_future() = default;
0390
0391 ~shared_future() = default;
0392
0393 inline
0394 shared_future( shared_future const& other) :
0395 base_type{ other } {
0396 }
0397
0398 inline
0399 shared_future( shared_future && other) noexcept :
0400 base_type{ std::move( other) } {
0401 }
0402
0403 inline
0404 shared_future( future< void > && other) noexcept :
0405 base_type{ std::move( other) } {
0406 }
0407
0408 inline
0409 shared_future & operator=( shared_future const& other) noexcept {
0410 if ( BOOST_LIKELY( this != & other) ) {
0411 base_type::operator=( other);
0412 }
0413 return * this;
0414 }
0415
0416 inline
0417 shared_future & operator=( shared_future && other) noexcept {
0418 if ( BOOST_LIKELY( this != & other) ) {
0419 base_type::operator=( std::move( other) );
0420 }
0421 return * this;
0422 }
0423
0424 inline
0425 shared_future & operator=( future< void > && other) noexcept {
0426 base_type::operator=( std::move( other) );
0427 return * this;
0428 }
0429
0430 inline
0431 void get() const {
0432 if ( BOOST_UNLIKELY( ! valid() ) ) {
0433 throw future_uninitialized{};
0434 }
0435 base_type::state_->get();
0436 }
0437
0438 using base_type::valid;
0439 using base_type::get_exception_ptr;
0440 using base_type::wait;
0441 using base_type::wait_for;
0442 using base_type::wait_until;
0443 };
0444
0445
0446 template< typename R >
0447 shared_future< R >
0448 future< R >::share() {
0449 if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
0450 throw future_uninitialized{};
0451 }
0452 return shared_future< R >{ std::move( * this) };
0453 }
0454
0455 template< typename R >
0456 shared_future< R & >
0457 future< R & >::share() {
0458 if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
0459 throw future_uninitialized{};
0460 }
0461 return shared_future< R & >{ std::move( * this) };
0462 }
0463
0464 inline
0465 shared_future< void >
0466 future< void >::share() {
0467 if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
0468 throw future_uninitialized{};
0469 }
0470 return shared_future< void >{ std::move( * this) };
0471 }
0472
0473 }}
0474
0475 #endif