File indexing completed on 2025-01-18 09:30:32
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_YIELD_H
0008 #define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_YIELD_H
0009
0010 #include <algorithm>
0011
0012 #include <boost/assert.hpp>
0013 #include <boost/config.hpp>
0014 #include <boost/move/move.hpp>
0015 #include <boost/throw_exception.hpp>
0016 #include <boost/type_traits/is_same.hpp>
0017 #include <boost/utility/enable_if.hpp>
0018 #include <boost/utility/explicit_operator_bool.hpp>
0019
0020 #include <boost/coroutine/detail/config.hpp>
0021 #include <boost/coroutine/exceptions.hpp>
0022
0023 #ifdef BOOST_HAS_ABI_HEADERS
0024 # include BOOST_ABI_PREFIX
0025 #endif
0026
0027 namespace boost {
0028 namespace coroutines {
0029 namespace detail {
0030
0031 template< typename R >
0032 class symmetric_coroutine_yield
0033 {
0034 private:
0035 template< typename X, typename Y, typename Z >
0036 friend class symmetric_coroutine_object;
0037
0038 typedef symmetric_coroutine_impl< R > impl_type;
0039
0040 struct dummy {};
0041
0042 BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_yield)
0043
0044 impl_type * impl_;
0045 R * result_;
0046
0047 symmetric_coroutine_yield( impl_type * impl, R * result) BOOST_NOEXCEPT :
0048 impl_( impl),
0049 result_( result)
0050 {
0051 BOOST_ASSERT( 0 != impl_);
0052 BOOST_ASSERT( 0 != result_);
0053 }
0054
0055 public:
0056 symmetric_coroutine_yield() BOOST_NOEXCEPT :
0057 impl_( 0),
0058 result_( 0)
0059 {}
0060
0061 symmetric_coroutine_yield( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT :
0062 impl_( 0),
0063 result_( 0)
0064 { swap( other); }
0065
0066 symmetric_coroutine_yield & operator=( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT
0067 {
0068 symmetric_coroutine_yield tmp( boost::move( other) );
0069 swap( tmp);
0070 return * this;
0071 }
0072
0073 BOOST_EXPLICIT_OPERATOR_BOOL();
0074
0075 bool operator!() const BOOST_NOEXCEPT
0076 { return 0 == impl_; }
0077
0078 void swap( symmetric_coroutine_yield & other) BOOST_NOEXCEPT
0079 {
0080 std::swap( impl_, other.impl_);
0081 std::swap( result_, other.result_);
0082 }
0083
0084 symmetric_coroutine_yield & operator()()
0085 {
0086 result_ = impl_->yield();
0087 return * this;
0088 }
0089
0090 template< typename Coro >
0091 symmetric_coroutine_yield & operator()( Coro & other, typename Coro::value_type x,
0092 typename disable_if<
0093 is_same< typename Coro::value_type, void >,
0094 dummy*
0095 >::type = 0)
0096 {
0097 BOOST_ASSERT( other);
0098
0099 result_ = impl_->yield_to( other.impl_, x);
0100 return * this;
0101 }
0102
0103 template< typename Coro >
0104 symmetric_coroutine_yield & operator()( Coro & other,
0105 typename enable_if<
0106 is_same< typename Coro::value_type, void >,
0107 dummy*
0108 >::type = 0)
0109 {
0110 BOOST_ASSERT( other);
0111
0112 result_ = impl_->yield_to( other.impl_);
0113 return * this;
0114 }
0115
0116 R get() const
0117 {
0118 if ( 0 == result_)
0119 boost::throw_exception(
0120 invalid_result() );
0121
0122 return * result_;
0123 }
0124 };
0125
0126 template< typename R >
0127 class symmetric_coroutine_yield< R & >
0128 {
0129 private:
0130 template< typename X, typename Y, typename Z >
0131 friend class symmetric_coroutine_object;
0132
0133 typedef symmetric_coroutine_impl< R & > impl_type;
0134
0135 struct dummy {};
0136
0137 BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_yield)
0138
0139 impl_type * impl_;
0140 R * result_;
0141
0142 symmetric_coroutine_yield( impl_type * impl, R * result) BOOST_NOEXCEPT :
0143 impl_( impl),
0144 result_( result)
0145 {
0146 BOOST_ASSERT( 0 != impl_);
0147 BOOST_ASSERT( 0 != result_);
0148 }
0149
0150 public:
0151 symmetric_coroutine_yield() BOOST_NOEXCEPT :
0152 impl_( 0),
0153 result_( 0)
0154 {}
0155
0156 symmetric_coroutine_yield( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT :
0157 impl_( 0),
0158 result_( 0)
0159 { swap( other); }
0160
0161 symmetric_coroutine_yield & operator=( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT
0162 {
0163 symmetric_coroutine_yield tmp( boost::move( other) );
0164 swap( tmp);
0165 return * this;
0166 }
0167
0168 BOOST_EXPLICIT_OPERATOR_BOOL();
0169
0170 bool operator!() const BOOST_NOEXCEPT
0171 { return 0 == impl_; }
0172
0173 void swap( symmetric_coroutine_yield & other) BOOST_NOEXCEPT
0174 {
0175 std::swap( impl_, other.impl_);
0176 std::swap( result_, other.result_);
0177 }
0178
0179 symmetric_coroutine_yield & operator()()
0180 {
0181 result_ = impl_->yield();
0182 return * this;
0183 }
0184
0185 template< typename Coro >
0186 symmetric_coroutine_yield & operator()( Coro & other, typename Coro::value_type & x,
0187 typename disable_if<
0188 is_same< typename Coro::value_type, void >,
0189 dummy*
0190 >::type = 0)
0191 {
0192 BOOST_ASSERT( other);
0193
0194 result_ = impl_->yield_to( other.impl_, x);
0195 return * this;
0196 }
0197
0198 template< typename Coro >
0199 symmetric_coroutine_yield & operator()( Coro & other,
0200 typename enable_if<
0201 is_same< typename Coro::value_type, void >,
0202 dummy*
0203 >::type = 0)
0204 {
0205 BOOST_ASSERT( other);
0206
0207 result_ = impl_->yield_to( other.impl_);
0208 return * this;
0209 }
0210
0211 R & get() const
0212 {
0213 if ( 0 == result_)
0214 boost::throw_exception(
0215 invalid_result() );
0216
0217 return * result_;
0218 }
0219 };
0220
0221 template<>
0222 class symmetric_coroutine_yield< void >
0223 {
0224 private:
0225 template< typename X, typename Y, typename Z >
0226 friend class symmetric_coroutine_object;
0227
0228 typedef symmetric_coroutine_impl< void > impl_type;
0229
0230 struct dummy {};
0231
0232 BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_yield)
0233
0234 impl_type * impl_;
0235
0236 symmetric_coroutine_yield( impl_type * impl) BOOST_NOEXCEPT :
0237 impl_( impl)
0238 { BOOST_ASSERT( 0 != impl_); }
0239
0240 public:
0241 symmetric_coroutine_yield() BOOST_NOEXCEPT :
0242 impl_( 0)
0243 {}
0244
0245 symmetric_coroutine_yield( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT :
0246 impl_( 0)
0247 { swap( other); }
0248
0249 symmetric_coroutine_yield & operator=( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT
0250 {
0251 symmetric_coroutine_yield tmp( boost::move( other) );
0252 swap( tmp);
0253 return * this;
0254 }
0255
0256 BOOST_EXPLICIT_OPERATOR_BOOL();
0257
0258 inline bool operator!() const BOOST_NOEXCEPT
0259 { return 0 == impl_; }
0260
0261 inline void swap( symmetric_coroutine_yield & other) BOOST_NOEXCEPT
0262 { std::swap( impl_, other.impl_); }
0263
0264 inline symmetric_coroutine_yield & operator()()
0265 {
0266 impl_->yield();
0267 return * this;
0268 }
0269
0270 template< typename Coro >
0271 symmetric_coroutine_yield & operator()( Coro & other, typename Coro::value_type & x,
0272 typename disable_if<
0273 is_same< typename Coro::value_type, void >,
0274 dummy*
0275 >::type = 0)
0276 {
0277 BOOST_ASSERT( other);
0278
0279 impl_->yield_to( other.impl_, x);
0280 return * this;
0281 }
0282
0283 template< typename Coro >
0284 symmetric_coroutine_yield & operator()( Coro & other,
0285 typename enable_if<
0286 is_same< typename Coro::value_type, void >,
0287 dummy*
0288 >::type = 0)
0289 {
0290 BOOST_ASSERT( other);
0291
0292 impl_->yield_to( other.impl_);
0293 return * this;
0294 }
0295 };
0296
0297 template< typename R >
0298 void swap( symmetric_coroutine_yield< R > & l, symmetric_coroutine_yield< R > & r)
0299 { l.swap( r); }
0300
0301 }}}
0302
0303 #ifdef BOOST_HAS_ABI_HEADERS
0304 # include BOOST_ABI_SUFFIX
0305 #endif
0306
0307 #endif