Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:31

0001 
0002 //          Copyright Oliver Kowalke 2009.
0003 // Distributed under the Boost Software License, Version 1.0.
0004 //    (See accompanying file LICENSE_1_0.txt or copy at
0005 //          http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H
0008 #define BOOST_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H
0009 
0010 #include <boost/assert.hpp>
0011 #include <boost/config.hpp>
0012 #include <boost/exception_ptr.hpp>
0013 #include <boost/throw_exception.hpp>
0014 #include <boost/utility.hpp>
0015 
0016 #include <boost/coroutine/detail/config.hpp>
0017 #include <boost/coroutine/detail/coroutine_context.hpp>
0018 #include <boost/coroutine/detail/flags.hpp>
0019 #include <boost/coroutine/detail/parameters.hpp>
0020 #include <boost/coroutine/detail/trampoline_pull.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 
0030 struct stack_context;
0031 
0032 namespace detail {
0033 
0034 template< typename R >
0035 class pull_coroutine_impl : private noncopyable
0036 {
0037 protected:
0038     int                     flags_;
0039     exception_ptr           except_;
0040     coroutine_context   *   caller_;
0041     coroutine_context   *   callee_;
0042     R                   *   result_;
0043 
0044 public:
0045     typedef parameters< R >                           param_type;
0046 
0047     pull_coroutine_impl( coroutine_context * caller,
0048                          coroutine_context * callee,
0049                          bool unwind) :
0050         flags_( 0),
0051         except_(),
0052         caller_( caller),
0053         callee_( callee),
0054         result_( 0)
0055     {
0056         if ( unwind) flags_ |= flag_force_unwind;
0057     }
0058 
0059     pull_coroutine_impl( coroutine_context * caller,
0060                          coroutine_context * callee,
0061                          bool unwind,
0062                          R * result) :
0063         flags_( 0),
0064         except_(),
0065         caller_( caller),
0066         callee_( callee),
0067         result_( result)
0068     {
0069         if ( unwind) flags_ |= flag_force_unwind;
0070     }
0071 
0072     virtual ~pull_coroutine_impl() {}
0073 
0074     bool force_unwind() const BOOST_NOEXCEPT
0075     { return 0 != ( flags_ & flag_force_unwind); }
0076 
0077     bool unwind_requested() const BOOST_NOEXCEPT
0078     { return 0 != ( flags_ & flag_unwind_stack); }
0079 
0080     bool is_started() const BOOST_NOEXCEPT
0081     { return 0 != ( flags_ & flag_started); }
0082 
0083     bool is_running() const BOOST_NOEXCEPT
0084     { return 0 != ( flags_ & flag_running); }
0085 
0086     bool is_complete() const BOOST_NOEXCEPT
0087     { return 0 != ( flags_ & flag_complete); }
0088 
0089     void unwind_stack() BOOST_NOEXCEPT
0090     {
0091         if ( is_started() && ! is_complete() && force_unwind() )
0092         {
0093             flags_ |= flag_unwind_stack;
0094             param_type to( unwind_t::force_unwind);
0095             caller_->jump(
0096                 * callee_,
0097                 & to);
0098             flags_ &= ~flag_unwind_stack;
0099 
0100             BOOST_ASSERT( is_complete() );
0101         }
0102     }
0103 
0104     void pull()
0105     {
0106         BOOST_ASSERT( ! is_running() );
0107         BOOST_ASSERT( ! is_complete() );
0108 
0109         flags_ |= flag_running;
0110         param_type to( this);
0111         param_type * from(
0112             static_cast< param_type * >(
0113                 caller_->jump(
0114                     * callee_,
0115                     & to) ) );
0116         flags_ &= ~flag_running;
0117         result_ = from->data;
0118         if ( from->do_unwind) throw forced_unwind();
0119         if ( except_) rethrow_exception( except_);
0120     }
0121 
0122     bool has_result() const
0123     { return 0 != result_; }
0124 
0125     R get() const
0126     {
0127         if ( ! has_result() )
0128             boost::throw_exception(
0129                 invalid_result() );
0130         return * result_;
0131     }
0132 
0133     R * get_pointer() const
0134     {
0135         if ( ! has_result() )
0136             boost::throw_exception(
0137                 invalid_result() );
0138         return result_;
0139     }
0140 
0141     virtual void destroy() = 0;
0142 };
0143 
0144 template< typename R >
0145 class pull_coroutine_impl< R & > : private noncopyable
0146 {
0147 protected:
0148     int                     flags_;
0149     exception_ptr           except_;
0150     coroutine_context   *   caller_;
0151     coroutine_context   *   callee_;
0152     R                   *   result_;
0153 
0154 public:
0155     typedef parameters< R & >                           param_type;
0156 
0157     pull_coroutine_impl( coroutine_context * caller,
0158                          coroutine_context * callee,
0159                          bool unwind) :
0160         flags_( 0),
0161         except_(),
0162         caller_( caller),
0163         callee_( callee),
0164         result_( 0)
0165     {
0166         if ( unwind) flags_ |= flag_force_unwind;
0167     }
0168 
0169     pull_coroutine_impl( coroutine_context * caller,
0170                          coroutine_context * callee,
0171                          bool unwind,
0172                          R * result) :
0173         flags_( 0),
0174         except_(),
0175         caller_( caller),
0176         callee_( callee),
0177         result_( result)
0178     {
0179         if ( unwind) flags_ |= flag_force_unwind;
0180     }
0181 
0182     virtual ~pull_coroutine_impl() {}
0183 
0184     bool force_unwind() const BOOST_NOEXCEPT
0185     { return 0 != ( flags_ & flag_force_unwind); }
0186 
0187     bool unwind_requested() const BOOST_NOEXCEPT
0188     { return 0 != ( flags_ & flag_unwind_stack); }
0189 
0190     bool is_started() const BOOST_NOEXCEPT
0191     { return 0 != ( flags_ & flag_started); }
0192 
0193     bool is_running() const BOOST_NOEXCEPT
0194     { return 0 != ( flags_ & flag_running); }
0195 
0196     bool is_complete() const BOOST_NOEXCEPT
0197     { return 0 != ( flags_ & flag_complete); }
0198 
0199     void unwind_stack() BOOST_NOEXCEPT
0200     {
0201         if ( is_started() && ! is_complete() && force_unwind() )
0202         {
0203             flags_ |= flag_unwind_stack;
0204             param_type to( unwind_t::force_unwind);
0205             caller_->jump(
0206                 * callee_,
0207                 & to);
0208             flags_ &= ~flag_unwind_stack;
0209 
0210             BOOST_ASSERT( is_complete() );
0211         }
0212     }
0213 
0214     void pull()
0215     {
0216         BOOST_ASSERT( ! is_running() );
0217         BOOST_ASSERT( ! is_complete() );
0218 
0219         flags_ |= flag_running;
0220         param_type to( this);
0221         param_type * from(
0222             static_cast< param_type * >(
0223                 caller_->jump(
0224                     * callee_,
0225                     & to) ) );
0226         flags_ &= ~flag_running;
0227         result_ = from->data;
0228         if ( from->do_unwind) throw forced_unwind();
0229         if ( except_) rethrow_exception( except_);
0230     }
0231 
0232     bool has_result() const
0233     { return 0 != result_; }
0234 
0235     R & get() const
0236     {
0237         if ( ! has_result() )
0238             boost::throw_exception(
0239                 invalid_result() );
0240         return * result_;
0241     }
0242 
0243     R * get_pointer() const
0244     {
0245         if ( ! has_result() )
0246             boost::throw_exception(
0247                 invalid_result() );
0248         return result_;
0249     }
0250 
0251     virtual void destroy() = 0;
0252 };
0253 
0254 template<>
0255 class pull_coroutine_impl< void > : private noncopyable
0256 {
0257 protected:
0258     int                     flags_;
0259     exception_ptr           except_;
0260     coroutine_context   *   caller_;
0261     coroutine_context   *   callee_;
0262 
0263 public:
0264     typedef parameters< void >      param_type;
0265 
0266     pull_coroutine_impl( coroutine_context * caller,
0267                          coroutine_context * callee,
0268                          bool unwind) :
0269         flags_( 0),
0270         except_(),
0271         caller_( caller),
0272         callee_( callee)
0273     {
0274         if ( unwind) flags_ |= flag_force_unwind;
0275     }
0276 
0277     virtual ~pull_coroutine_impl() {}
0278 
0279     inline bool force_unwind() const BOOST_NOEXCEPT
0280     { return 0 != ( flags_ & flag_force_unwind); }
0281 
0282     inline bool unwind_requested() const BOOST_NOEXCEPT
0283     { return 0 != ( flags_ & flag_unwind_stack); }
0284 
0285     inline bool is_started() const BOOST_NOEXCEPT
0286     { return 0 != ( flags_ & flag_started); }
0287 
0288     inline bool is_running() const BOOST_NOEXCEPT
0289     { return 0 != ( flags_ & flag_running); }
0290 
0291     inline bool is_complete() const BOOST_NOEXCEPT
0292     { return 0 != ( flags_ & flag_complete); }
0293 
0294     inline void unwind_stack() BOOST_NOEXCEPT
0295     {
0296         if ( is_started() && ! is_complete() && force_unwind() )
0297         {
0298             flags_ |= flag_unwind_stack;
0299             param_type to( unwind_t::force_unwind);
0300             caller_->jump(
0301                 * callee_,
0302                 & to);
0303             flags_ &= ~flag_unwind_stack;
0304 
0305             BOOST_ASSERT( is_complete() );
0306         }
0307     }
0308 
0309     inline void pull()
0310     {
0311         BOOST_ASSERT( ! is_running() );
0312         BOOST_ASSERT( ! is_complete() );
0313 
0314         flags_ |= flag_running;
0315         param_type to( this);
0316         param_type * from(
0317             static_cast< param_type * >(
0318                 caller_->jump(
0319                     * callee_,
0320                     & to) ) );
0321         flags_ &= ~flag_running;
0322         if ( from->do_unwind) throw forced_unwind();
0323         if ( except_) rethrow_exception( except_);
0324     }
0325 
0326     virtual void destroy() = 0;
0327 };
0328 
0329 }}}
0330 
0331 #ifdef BOOST_HAS_ABI_HEADERS
0332 #  include BOOST_ABI_SUFFIX
0333 #endif
0334 
0335 #endif // BOOST_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H