Imported existing code
This commit is contained in:
34
libraries/include/boost/coroutine/detail/arg_max.hpp
Normal file
34
libraries/include/boost/coroutine/detail/arg_max.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_ARG_MAX_HPP_20060728
|
||||
# define BOOST_COROUTINE_DETAIL_ARG_MAX_HPP_20060728
|
||||
# ifndef BOOST_COROUTINE_ARG_MAX
|
||||
# define BOOST_COROUTINE_ARG_MAX 10
|
||||
# endif
|
||||
#endif
|
||||
70
libraries/include/boost/coroutine/detail/argument_packer.hpp
Normal file
70
libraries/include/boost/coroutine/detail/argument_packer.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_ARGUMENT_PACKER_HPP_20060601
|
||||
#define BOOST_COROUTINE_ARGUMENT_PACKER_HPP_20060601
|
||||
#include <boost/preprocessor/control/if.hpp>
|
||||
#include <boost/preprocessor/punctuation/comma_if.hpp>
|
||||
#include <boost/preprocessor/repetition.hpp>
|
||||
#include <boost/preprocessor/tuple/eat.hpp>
|
||||
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
#define BOOST_COROUTINE_DETAIL_TEMPLATE_PARAMETERS(n) \
|
||||
template<BOOST_PP_ENUM_PARAMS(n, typename T)> \
|
||||
/**/
|
||||
|
||||
#define BOOST_COROUTINE_ARGUMENT_PACKER(z, n, parm_tuple) \
|
||||
BOOST_PP_IF(n, \
|
||||
BOOST_COROUTINE_DETAIL_TEMPLATE_PARAMETERS , \
|
||||
BOOST_PP_TUPLE_EAT(1) )(n) \
|
||||
BOOST_PP_TUPLE_ELEM(3, 0, parm_tuple) \
|
||||
(BOOST_PP_ENUM_BINARY_PARAMS(n, T, arg)) { \
|
||||
typedef BOOST_PP_TUPLE_ELEM(3, 2, parm_tuple) parm_type; \
|
||||
return BOOST_PP_TUPLE_ELEM(3, 1, parm_tuple) \
|
||||
(parm_type \
|
||||
(BOOST_PP_ENUM_PARAMS(n, arg))); \
|
||||
} \
|
||||
/**/
|
||||
|
||||
|
||||
#define BOOST_COROUTINE_ARGUMENT_PACKER_EX(z, n, parm_tuple) \
|
||||
template<typename Arg \
|
||||
BOOST_PP_COMMA_IF(n) \
|
||||
BOOST_PP_ENUM_PARAMS(n, typename T)> \
|
||||
BOOST_PP_TUPLE_ELEM(3, 0, parm_tuple) \
|
||||
(Arg arg \
|
||||
BOOST_PP_COMMA_IF(n) \
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(n, T, arg)) { \
|
||||
typedef BOOST_PP_TUPLE_ELEM(3, 2, parm_tuple) parm_type; \
|
||||
return BOOST_PP_TUPLE_ELEM(3, 1, parm_tuple)( arg, parm_type \
|
||||
(BOOST_PP_ENUM_PARAMS(n, arg))); \
|
||||
} \
|
||||
/**/
|
||||
|
||||
} } }
|
||||
#endif
|
||||
134
libraries/include/boost/coroutine/detail/argument_unpacker.hpp
Normal file
134
libraries/include/boost/coroutine/detail/argument_unpacker.hpp
Normal file
@@ -0,0 +1,134 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_ARGUMENT_UNPACKER_HPP_20060601
|
||||
#define BOOST_COROUTINE_ARGUMENT_UNPACKER_HPP_20060601
|
||||
#include <boost/preprocessor/control/if.hpp>
|
||||
#include <boost/preprocessor/repetition.hpp>
|
||||
#include <boost/utility/result_of.hpp>
|
||||
#include <boost/coroutine/detail/index.hpp>
|
||||
#include <boost/coroutine/detail/arg_max.hpp>
|
||||
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
template<typename Traits, int Len>
|
||||
struct unpacker_n;
|
||||
|
||||
template<typename Traits, int Len>
|
||||
struct unpacker_ex_n;
|
||||
|
||||
|
||||
#define BOOST_COROUTINE_ARGUMENT_UNPACKER(z, len, unused) \
|
||||
template<typename Traits> \
|
||||
struct unpacker_n<Traits, len> { \
|
||||
template<typename Functor, typename Tuple> \
|
||||
struct result {/*for result_of compatibility*/ \
|
||||
typedef typename boost::result_of \
|
||||
<Functor(BOOST_PP_ENUM_BINARY_PARAMS \
|
||||
(len, typename Traits::template at<index_ , > \
|
||||
::type BOOST_PP_INTERCEPT))>::type type; \
|
||||
}; \
|
||||
template<typename Functor, typename Tuple> \
|
||||
typename result<Functor, Tuple>::type operator() \
|
||||
(Functor& f, Tuple& parms){ \
|
||||
using boost::get; /*tuples::get cannot be found via ADL*/ \
|
||||
return f(BOOST_PP_ENUM_BINARY_PARAMS \
|
||||
(len, \
|
||||
get<index_, > \
|
||||
(parms) BOOST_PP_INTERCEPT)); \
|
||||
} \
|
||||
}; \
|
||||
/**/
|
||||
|
||||
#define BOOST_COROUTINE_ARGUMENT_UNPACKER_EX(z, len, unused) \
|
||||
template<typename Traits> \
|
||||
struct unpacker_ex_n<Traits, len > { \
|
||||
template<typename Functor, \
|
||||
typename First, \
|
||||
typename Tuple> \
|
||||
struct result { \
|
||||
typedef typename boost::result_of \
|
||||
<Functor(First BOOST_PP_COMMA_IF(len) \
|
||||
BOOST_PP_ENUM_BINARY_PARAMS \
|
||||
(len, typename Traits \
|
||||
::template at<index_ , >::type BOOST_PP_INTERCEPT))> \
|
||||
::type type; \
|
||||
}; \
|
||||
\
|
||||
template<typename Functor, \
|
||||
typename First, \
|
||||
typename Tuple> \
|
||||
typename result<Functor, First, Tuple>::type \
|
||||
operator()(Functor& f, First& arg0, Tuple& parms){ \
|
||||
using boost::get; /*tuples::get cannot be found via ADL*/ \
|
||||
return f(arg0 \
|
||||
BOOST_PP_COMMA_IF(len) \
|
||||
BOOST_PP_ENUM_BINARY_PARAMS \
|
||||
(len, \
|
||||
get<index_, > \
|
||||
(parms) BOOST_PP_INTERCEPT) ); \
|
||||
} \
|
||||
}; \
|
||||
/**/
|
||||
|
||||
BOOST_PP_REPEAT(BOOST_COROUTINE_ARG_MAX,
|
||||
BOOST_COROUTINE_ARGUMENT_UNPACKER, ~);
|
||||
BOOST_PP_REPEAT(BOOST_COROUTINE_ARG_MAX,
|
||||
BOOST_COROUTINE_ARGUMENT_UNPACKER_EX, ~);
|
||||
|
||||
// Somehow VCPP 8.0 chockes if the Trait for unpack[_ex]
|
||||
// is explicitly specified. We use an empty dispatch
|
||||
// tag to let the compiler deduce it.
|
||||
template<typename Trait>
|
||||
struct trait_tag {};
|
||||
|
||||
/**
|
||||
* Inovoke function object @p f passing all
|
||||
* elements in tuple @p parms as distinct parameters.
|
||||
*/
|
||||
template<typename Traits, typename Functor, typename Tuple>
|
||||
inline
|
||||
typename unpacker_n<Traits, Traits::length>
|
||||
::template result<Functor, Tuple>::type
|
||||
unpack(Functor f, Tuple& parms, trait_tag<Traits>) {
|
||||
return unpacker_n<Traits, Traits::length>()(f, parms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inovke function object @p f passing argument @p arg0 and all
|
||||
* elements in tuple @p parms as distinct parameters.
|
||||
*/
|
||||
template<typename Traits, typename Functor, typename First, typename Tuple>
|
||||
inline
|
||||
typename unpacker_ex_n<Traits, Traits::length>::
|
||||
template result<Functor, First, Tuple>::type
|
||||
unpack_ex(Functor f, First& arg0, Tuple& parms, trait_tag<Traits>) {
|
||||
return unpacker_ex_n<Traits, Traits::length>()
|
||||
(f, arg0, parms);
|
||||
}
|
||||
} } }
|
||||
#endif
|
||||
123
libraries/include/boost/coroutine/detail/call_impl.hpp
Normal file
123
libraries/include/boost/coroutine/detail/call_impl.hpp
Normal file
@@ -0,0 +1,123 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_CALL_IMPL_HPP_20060728
|
||||
#define BOOST_COROUTINE_DETAIL_CALL_IMPL_HPP_20060728
|
||||
|
||||
#include <boost/preprocessor/repetition.hpp>
|
||||
#include <boost/call_traits.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/coroutine/coroutine.hpp>
|
||||
#include <boost/coroutine/detail/arg_max.hpp>
|
||||
#include <boost/coroutine/detail/signal.hpp>
|
||||
#include <boost/coroutine/detail/coroutine_accessor.hpp>
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
|
||||
#define BOOST_COROUTINE_tuple_param_n(z, n, tuple)\
|
||||
BOOST_DEDUCED_TYPENAME \
|
||||
boost::tuples::element<n, tuple>::type \
|
||||
BOOST_PP_CAT(arg, n) \
|
||||
/**/
|
||||
|
||||
template<typename Future>
|
||||
class callback {
|
||||
public:
|
||||
|
||||
typedef void result_type;
|
||||
|
||||
callback(Future& future) :
|
||||
m_future_pimpl(wait_gateway::get_impl(future)) {
|
||||
m_future_pimpl->mark_pending();
|
||||
}
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
Future::tuple_type tuple_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
Future::tuple_traits_type tuple_traits_type;
|
||||
|
||||
/*
|
||||
* By default a callback is one shot only.
|
||||
* By calling this method you can revive a
|
||||
* callback for another shot.
|
||||
* You must guaranee that the future
|
||||
* is still alive.
|
||||
*/
|
||||
void revive() {
|
||||
m_future_pimpl->mark_pending();
|
||||
}
|
||||
|
||||
#define BOOST_COROUTINE_gen_argn_type(z, n, unused) \
|
||||
typedef BOOST_DEDUCED_TYPENAME \
|
||||
tuple_traits_type:: \
|
||||
template at<n>::type \
|
||||
BOOST_PP_CAT(BOOST_PP_CAT(arg, n), _type); \
|
||||
/**/
|
||||
|
||||
BOOST_PP_REPEAT(BOOST_COROUTINE_ARG_MAX,
|
||||
BOOST_COROUTINE_gen_argn_type,
|
||||
~);
|
||||
|
||||
#define BOOST_COROUTINE_param_with_default(z, n, type_prefix) \
|
||||
BOOST_DEDUCED_TYPENAME call_traits \
|
||||
<BOOST_PP_CAT(BOOST_PP_CAT(type_prefix, n), _type)> \
|
||||
::param_type \
|
||||
BOOST_PP_CAT(arg, n) = \
|
||||
BOOST_PP_CAT(BOOST_PP_CAT(type_prefix, n), _type)() \
|
||||
/**/
|
||||
|
||||
void operator()
|
||||
(BOOST_PP_ENUM
|
||||
(BOOST_COROUTINE_ARG_MAX,
|
||||
BOOST_COROUTINE_param_with_default,
|
||||
arg)) {
|
||||
m_future_pimpl->assign(tuple_type
|
||||
(BOOST_PP_ENUM_PARAMS
|
||||
(BOOST_COROUTINE_ARG_MAX, arg)));
|
||||
}
|
||||
|
||||
private:
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
Future::impl_pointer
|
||||
m_future_pimpl;
|
||||
};
|
||||
|
||||
#undef BOOST_COROUTINE_gen_future_assigner
|
||||
#undef BOOST_COROUTINE_tuple_param_n
|
||||
|
||||
template<typename Future, typename Functor, typename CoroutineSelf>
|
||||
Future call_impl(Functor fun, const CoroutineSelf& coro_self) {
|
||||
Future future(coro_self);
|
||||
fun(callback<Future>(future));
|
||||
return future;
|
||||
}
|
||||
|
||||
} } }
|
||||
|
||||
#endif
|
||||
416
libraries/include/boost/coroutine/detail/context_base.hpp
Normal file
416
libraries/include/boost/coroutine/detail/context_base.hpp
Normal file
@@ -0,0 +1,416 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_CONTEXT_IMPL_HPP_20060810
|
||||
#define BOOST_COROUTINE_CONTEXT_IMPL_HPP_20060810
|
||||
/*
|
||||
* Currently asio can, in some cases. call copy constructors and
|
||||
* operator= from different threads, even if in the
|
||||
* one-thread-per-service model. (i.e. from the resolver thread)
|
||||
* This will be corrected in future versions, but for now
|
||||
* we will play it safe and use an atomic count. The overhead shouldn't
|
||||
* be big.
|
||||
*/
|
||||
#define BOOST_COROUTINE_USE_ATOMIC_COUNT
|
||||
|
||||
#ifdef BOOST_COROUTINE_USE_ATOMIC_COUNT
|
||||
# include <boost/detail/atomic_count.hpp>
|
||||
#endif
|
||||
#include <cstddef>
|
||||
#include <algorithm> //for swap
|
||||
#include <boost/coroutine/detail/swap_context.hpp> //for swap hints
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <boost/coroutine/exception.hpp>
|
||||
#include <boost/coroutine/detail/noreturn.hpp>
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
|
||||
const std::ptrdiff_t default_stack_size = -1;
|
||||
|
||||
template<typename ContextImpl>
|
||||
class context_base : public ContextImpl {
|
||||
public:
|
||||
|
||||
typedef ContextImpl context_impl;
|
||||
typedef context_base<context_impl> type;
|
||||
typedef boost::intrusive_ptr<type> pointer;
|
||||
typedef void deleter_type(const type*);
|
||||
|
||||
template<typename Derived>
|
||||
context_base(Derived& derived,
|
||||
std::ptrdiff_t stack_size) :
|
||||
context_impl(derived, stack_size),
|
||||
m_counter(0),
|
||||
m_deleter(&deleter<Derived>),
|
||||
m_state(ctx_ready),
|
||||
m_exit_state(ctx_exit_not_requested),
|
||||
m_exit_status(ctx_not_exited),
|
||||
m_wait_counter(0),
|
||||
m_operation_counter(0),
|
||||
m_type_info(0) {}
|
||||
|
||||
friend
|
||||
void intrusive_ptr_add_ref(type * ctx) {
|
||||
ctx->acquire();
|
||||
}
|
||||
|
||||
friend
|
||||
void intrusive_ptr_release(type * ctx) {
|
||||
ctx->release();
|
||||
}
|
||||
|
||||
bool unique() const {
|
||||
return count() == 1;
|
||||
}
|
||||
|
||||
std::size_t count() const {
|
||||
return m_counter;
|
||||
}
|
||||
|
||||
void acquire() const {
|
||||
++m_counter;
|
||||
}
|
||||
|
||||
void release() const {
|
||||
BOOST_ASSERT(m_counter);
|
||||
if(--m_counter == 0) {
|
||||
m_deleter(this);
|
||||
}
|
||||
}
|
||||
|
||||
void count_down() throw() {
|
||||
BOOST_ASSERT(m_operation_counter) ;
|
||||
--m_operation_counter;
|
||||
}
|
||||
|
||||
void count_up() throw() {
|
||||
++m_operation_counter;
|
||||
}
|
||||
|
||||
// return true if there are operations pending.
|
||||
int pending() const {
|
||||
return m_operation_counter;
|
||||
}
|
||||
|
||||
/*
|
||||
* A signal may occur only when a context is
|
||||
* not running (is delivered sinchrononously).
|
||||
* This means that state MUST NOT be busy.
|
||||
* It may be ready or waiting.
|
||||
* returns 'ready()'.
|
||||
* Nothrow.
|
||||
*/
|
||||
bool signal () throw() {
|
||||
BOOST_ASSERT(!running() && !exited());
|
||||
BOOST_ASSERT(m_wait_counter) ;
|
||||
|
||||
--m_wait_counter;
|
||||
if(!m_wait_counter && m_state == ctx_waiting)
|
||||
m_state = ctx_ready;
|
||||
return ready();
|
||||
}
|
||||
|
||||
/*
|
||||
* Wake up a waiting context.
|
||||
* Similar to invoke(), but *does not
|
||||
* throw* if the coroutine exited normally
|
||||
* or entered the wait state.
|
||||
* It *does throw* if the coroutine
|
||||
* exited abnormally.
|
||||
* Return: false if invoke() would have thrown,
|
||||
* true otherwise.
|
||||
*
|
||||
*/
|
||||
bool wake_up() {
|
||||
BOOST_ASSERT(ready());
|
||||
do_invoke();
|
||||
// TODO: could use a binary 'or' here to eliminate
|
||||
// shortcut evaluation (and a branch), but maybe the compiler is
|
||||
// smart enough to do it anyway as there are no side effects.
|
||||
if(m_exit_status || m_state == ctx_waiting) {
|
||||
if(m_state == ctx_waiting)
|
||||
return false;
|
||||
if(m_exit_status == ctx_exited_return)
|
||||
return true;
|
||||
if(m_exit_status == ctx_exited_abnormally) {
|
||||
std::type_info const * tinfo =0;
|
||||
std::swap(m_type_info, tinfo);
|
||||
throw abnormal_exit(tinfo?*tinfo: typeid(unknown_exception_tag));
|
||||
} else if(m_exit_status == ctx_exited_exit)
|
||||
return false;
|
||||
else {
|
||||
BOOST_ASSERT(0 && "unkonw exit status");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* Returns true if the context is runnable.
|
||||
*/
|
||||
bool ready() const {
|
||||
return m_state == ctx_ready;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the context is in wait
|
||||
* state.
|
||||
*/
|
||||
bool waiting() const {
|
||||
return m_state == ctx_waiting;
|
||||
}
|
||||
|
||||
bool running() const {
|
||||
return m_state == ctx_running;
|
||||
}
|
||||
|
||||
bool exited() const {
|
||||
return m_state == ctx_exited;
|
||||
}
|
||||
|
||||
// Resume coroutine.
|
||||
// Pre: The coroutine must be ready.
|
||||
// Post: The coroutine relinquished control. It might be ready, waiting
|
||||
// or exited.
|
||||
// Throws:- 'waiting' if the coroutine entered the wait state,
|
||||
// - 'coroutine_exited' if the coroutine exited by an uncaught
|
||||
// 'exit_exception'.
|
||||
// - 'abnormal_exit' if the coroutine was exited by another
|
||||
// uncaught exception.
|
||||
// Note, it guarantees that the coroutine is resumed. Can throw only
|
||||
// on return.
|
||||
void invoke() {
|
||||
BOOST_ASSERT(ready());
|
||||
do_invoke();
|
||||
// TODO: could use a bynary or here to eliminate
|
||||
// shortcut evaluation (and a branch), but maybe the compiler is
|
||||
// smart enough to do it anyway as there are no side effects.
|
||||
if(m_exit_status || m_state == ctx_waiting) {
|
||||
if(m_state == ctx_waiting)
|
||||
throw waiting();
|
||||
if(m_exit_status == ctx_exited_return)
|
||||
return;
|
||||
if(m_exit_status == ctx_exited_abnormally) {
|
||||
std::type_info const * tinfo =0;
|
||||
std::swap(m_type_info, tinfo);
|
||||
throw abnormal_exit(tinfo?*tinfo: typeid(unknown_exception_tag));
|
||||
} else if(m_exit_status == ctx_exited_exit)
|
||||
throw coroutine_exited();
|
||||
else {
|
||||
BOOST_ASSERT(0 && "unkonw exit status");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Put coroutine in ready state and relinquish control
|
||||
// to caller until resumed again.
|
||||
// Pre: Coroutine is running.
|
||||
// Exit not pending.
|
||||
// Operations not pending.
|
||||
// Post: Coroutine is running.
|
||||
// Throws: exit_exception, if exit is pending *after* it has been
|
||||
// resumed.
|
||||
void yield() {
|
||||
BOOST_ASSERT(m_exit_state < ctx_exit_signaled); //prevent infinite loops
|
||||
BOOST_ASSERT(running());
|
||||
BOOST_ASSERT(!pending());
|
||||
|
||||
m_state = ctx_ready;
|
||||
do_yield();
|
||||
|
||||
BOOST_ASSERT(running());
|
||||
check_exit_state();
|
||||
}
|
||||
|
||||
//
|
||||
// If n > 0, put the coroutine in the wait state
|
||||
// then relinquish control to caller.
|
||||
// If n = 0 do nothing.
|
||||
// The coroutine will remain in the wait state until
|
||||
// is signaled 'n' times.
|
||||
// Pre: 0 <= n < pending()
|
||||
// Coroutine is running.
|
||||
// Exit not pending.
|
||||
// Post: Coroutine is running.
|
||||
// The coroutine has been signaled 'n' times unless an exit
|
||||
// has been signaled.
|
||||
// Throws: exit_exception.
|
||||
// FIXME: currently there is a BIG problem. A coroutine cannot
|
||||
// be exited as long as there are futures pending.
|
||||
// The exit_exception would cause the future to be destroyed and
|
||||
// an assertion to be generated. Removing an assertion is not a
|
||||
// solution because we would leak the coroutine impl. The callback
|
||||
// bound to the future in fact hold a refrence to it. If the coroutine
|
||||
// is exited the callback cannot be called.
|
||||
void wait(int n) {
|
||||
BOOST_ASSERT(!(n<0));
|
||||
BOOST_ASSERT(m_exit_state < ctx_exit_signaled); //prevent infinite loop
|
||||
BOOST_ASSERT(running());
|
||||
BOOST_ASSERT(!(pending() < n));
|
||||
|
||||
if(n == 0) return;
|
||||
m_wait_counter = n;
|
||||
|
||||
m_state = ctx_waiting;
|
||||
do_yield();
|
||||
|
||||
BOOST_ASSERT(m_state == ctx_running);
|
||||
check_exit_state();
|
||||
BOOST_ASSERT(m_wait_counter == 0);
|
||||
}
|
||||
|
||||
// Throws: exit_exception.
|
||||
void yield_to(context_base& to) {
|
||||
BOOST_ASSERT(m_exit_state < ctx_exit_signaled); //prevent infinite loops
|
||||
BOOST_ASSERT(m_state == ctx_running);
|
||||
BOOST_ASSERT(to.ready());
|
||||
BOOST_ASSERT(!to.pending());
|
||||
|
||||
std::swap(m_caller, to.m_caller);
|
||||
std::swap(m_state, to.m_state);
|
||||
swap_context(*this, to, detail::yield_to_hint());
|
||||
|
||||
BOOST_ASSERT(m_state == ctx_running);
|
||||
check_exit_state();
|
||||
}
|
||||
|
||||
// Cause this coroutine to exit.
|
||||
// Can only be called on a ready coroutine.
|
||||
// Cannot be called if there are pending operations.
|
||||
// It follws that cannot be called from 'this'.
|
||||
// Nothrow.
|
||||
void exit() throw(){
|
||||
BOOST_ASSERT(!pending());
|
||||
BOOST_ASSERT(ready()) ;
|
||||
if(m_exit_state < ctx_exit_pending)
|
||||
m_exit_state = ctx_exit_pending;
|
||||
do_invoke();
|
||||
BOOST_ASSERT(exited()); //at this point the coroutine MUST have exited.
|
||||
}
|
||||
|
||||
// Always throw exit_exception.
|
||||
// Never returns from standard control flow.
|
||||
BOOST_COROUTINE_NORETURN(void exit_self()) {
|
||||
BOOST_ASSERT(!pending());
|
||||
BOOST_ASSERT(running());
|
||||
m_exit_state = ctx_exit_pending;
|
||||
throw exit_exception();
|
||||
}
|
||||
|
||||
// Nothrow.
|
||||
~context_base() throw() {
|
||||
BOOST_ASSERT(!running());
|
||||
try {
|
||||
if(!exited())
|
||||
exit();
|
||||
BOOST_ASSERT(exited());
|
||||
} catch(...) {}
|
||||
}
|
||||
|
||||
protected:
|
||||
// global coroutine state
|
||||
enum context_state {
|
||||
ctx_running, // context running.
|
||||
ctx_ready, // context at yield point.
|
||||
ctx_waiting, // context waiting for events.
|
||||
ctx_exited // context is finished.
|
||||
};
|
||||
|
||||
// exit request state
|
||||
enum context_exit_state {
|
||||
ctx_exit_not_requested, // exit not requested.
|
||||
ctx_exit_pending, // exit requested.
|
||||
ctx_exit_signaled, // exit request delivered.
|
||||
};
|
||||
|
||||
// exit status
|
||||
enum context_exit_status {
|
||||
ctx_not_exited,
|
||||
ctx_exited_return, // process exited by return.
|
||||
ctx_exited_exit, // process exited by exit().
|
||||
ctx_exited_abnormally // process exited uncleanly.
|
||||
};
|
||||
|
||||
// Cause the coroutine to exit if
|
||||
// a exit request is pending.
|
||||
// Throws: exit_exception if an exit request is pending.
|
||||
void check_exit_state() {
|
||||
BOOST_ASSERT(running());
|
||||
if(!m_exit_state) return;
|
||||
throw exit_exception();
|
||||
}
|
||||
|
||||
// Nothrow.
|
||||
void do_return(context_exit_status status, std::type_info const* info) throw() {
|
||||
BOOST_ASSERT(status != ctx_not_exited);
|
||||
BOOST_ASSERT(m_state == ctx_running);
|
||||
m_type_info = info;
|
||||
m_state = ctx_exited;
|
||||
m_exit_status = status;
|
||||
do_yield();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Nothrow.
|
||||
void do_yield() throw() {
|
||||
swap_context(*this, m_caller, detail::yield_hint());
|
||||
}
|
||||
|
||||
// Nothrow.
|
||||
void do_invoke() throw (){
|
||||
BOOST_ASSERT(ready() || waiting());
|
||||
m_state = ctx_running;
|
||||
swap_context(m_caller, *this, detail::invoke_hint());
|
||||
}
|
||||
|
||||
template<typename ActualCtx>
|
||||
static void deleter (const type* ctx){
|
||||
delete static_cast<ActualCtx*>(const_cast<type*>(ctx));
|
||||
}
|
||||
|
||||
typedef typename context_impl::context_impl_base ctx_type;
|
||||
ctx_type m_caller;
|
||||
mutable
|
||||
#ifndef BOOST_COROUTINE_USE_ATOMIC_COUNT
|
||||
std::size_t
|
||||
#else
|
||||
boost::detail::atomic_count
|
||||
#endif
|
||||
m_counter;
|
||||
deleter_type * m_deleter;
|
||||
context_state m_state;
|
||||
context_exit_state m_exit_state;
|
||||
context_exit_status m_exit_status;
|
||||
int m_wait_counter;
|
||||
int m_operation_counter;
|
||||
|
||||
// This is used to generate a meaningful exception trace.
|
||||
std::type_info const* m_type_info;
|
||||
};
|
||||
|
||||
} } }
|
||||
#endif
|
||||
285
libraries/include/boost/coroutine/detail/context_linux.hpp
Normal file
285
libraries/include/boost/coroutine/detail/context_linux.hpp
Normal file
@@ -0,0 +1,285 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_CONTEXT_LINUX_HPP_20060601
|
||||
#define BOOST_COROUTINE_CONTEXT_LINUX_HPP_20060601
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__) && !defined(BOOST_COROUTINE_NO_ASM)
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <boost/coroutine/detail/posix_utility.hpp>
|
||||
#include <boost/coroutine/detail/swap_context.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
/*
|
||||
* Defining BOOST_COROUTINE_INLINE_ASM will enable the inlin3
|
||||
* assembler verwsion of swapcontext_stack.
|
||||
* The inline asm, with all required clobber flags, is usually no faster
|
||||
* than the out-of-line function, and it is not yet clear if
|
||||
* it is always reliable (i.e. if the compiler always saves the correct
|
||||
* registers). FIXME: it is currently missing at least MMX and XMM registers in
|
||||
* the clobber list.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Defining BOOST_COROUTINE_NO_SEPARATE_CALL_SITES will disable separate
|
||||
* invoke, yield and yield_to swap_context functions. Separate calls sites
|
||||
* increase performance by 25% at least on P4 for invoke+yield back loops
|
||||
* at the cost of a slightly higher instruction cache use and is thus enabled by
|
||||
* default.
|
||||
*/
|
||||
//#define BOOST_COROUTINE_NO_SEPARATE_CALL_SITES
|
||||
//#define BOOST_COROUTINE_INLINE_ASM
|
||||
|
||||
|
||||
#ifndef BOOST_COROUTINE_INLINE_ASM
|
||||
extern "C" void swapcontext_stack (void***, void**) throw() __attribute((regparm(2)));
|
||||
extern "C" void swapcontext_stack2 (void***, void**) throw() __attribute((regparm(2)));
|
||||
extern "C" void swapcontext_stack3 (void***, void**) throw() __attribute((regparm(2)));
|
||||
#else
|
||||
|
||||
# if 1
|
||||
void
|
||||
inline
|
||||
swapcontext_stack(void***from_sp, void**to_sp) throw() {
|
||||
asm volatile
|
||||
("\n\t pushl %%ebp"
|
||||
"\n\t pushl %[from]"
|
||||
"\n\t pushl %[to]"
|
||||
"\n\t pushl $0f"
|
||||
"\n\t movl %%esp, (%[from])"
|
||||
"\n\t movl %[to], %%esp"
|
||||
"\n\t popl %%ecx"
|
||||
"\n\t jmp *%%ecx"
|
||||
"\n0:\t popl %[to]"
|
||||
"\n\t popl %[from]"
|
||||
"\n\t popl %%ebp"
|
||||
::
|
||||
[from] "a" (from_sp),
|
||||
[to] "d" (to_sp)
|
||||
:
|
||||
"cc",
|
||||
"%ecx",
|
||||
"%ebx",
|
||||
"%edi",
|
||||
"%esi",
|
||||
"%st",
|
||||
"%st(1)",
|
||||
"%st(2)",
|
||||
"%st(3)",
|
||||
"%st(4)",
|
||||
"%st(5)",
|
||||
"%st(6)",
|
||||
"%st(7)",
|
||||
"memory"
|
||||
);
|
||||
|
||||
}
|
||||
# else
|
||||
typedef void (*fun_type)(void***from_sp, void**to_sp)
|
||||
__attribute((regparm(2)));
|
||||
|
||||
fun_type get_swapper();// __attribute__((pure));
|
||||
|
||||
inline
|
||||
fun_type get_swapper(){
|
||||
fun_type ptr;
|
||||
asm volatile("mov $0f, %[result]"
|
||||
"\n\t jmp 1f"
|
||||
"\n0:"
|
||||
//"\n\t movl 16(%%edx), %%ecx"
|
||||
"\n\t pushl %%ebp"
|
||||
"\n\t pushl %%ebx"
|
||||
"\n\t pushl %%esi"
|
||||
"\n\t pushl %%edi"
|
||||
"\n\t movl %%esp, (%%eax)"
|
||||
"\n\t movl %%edx, %%esp"
|
||||
"\n\t popl %%edi"
|
||||
"\n\t popl %%esi"
|
||||
"\n\t popl %%ebx"
|
||||
"\n\t popl %%ebp"
|
||||
"\n\t popl %%ecx"
|
||||
"\n\t jmp *%%ecx"
|
||||
"\n1:"
|
||||
:
|
||||
[result] "=g" (ptr)
|
||||
:
|
||||
);
|
||||
return ptr;
|
||||
};
|
||||
|
||||
void
|
||||
inline
|
||||
swapcontext_stack(void***from_sp, void**to_sp) throw() {
|
||||
fun_type ptr = get_swapper();
|
||||
ptr(from_sp, to_sp);
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
void
|
||||
inline
|
||||
swapcontext_stack2(void***from_sp, void**to_sp) throw() {
|
||||
swapcontext_stack(from_sp, to_sp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
namespace oslinux {
|
||||
template<typename T>
|
||||
void trampoline(T* fun);
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
void
|
||||
trampoline(T * fun) {
|
||||
(*fun)();
|
||||
std::abort();
|
||||
}
|
||||
|
||||
class ia32_gcc_context_impl_base {
|
||||
public:
|
||||
ia32_gcc_context_impl_base() {};
|
||||
|
||||
void prefetch() const {
|
||||
__builtin_prefetch (m_sp, 1, 3);
|
||||
__builtin_prefetch (m_sp, 0, 3);
|
||||
__builtin_prefetch ((void**)m_sp+64/4, 1, 3);
|
||||
__builtin_prefetch ((void**)m_sp+64/4, 0, 3);
|
||||
__builtin_prefetch ((void**)m_sp+32/4, 1, 3);
|
||||
__builtin_prefetch ((void**)m_sp+32/4, 0, 3);
|
||||
__builtin_prefetch ((void**)m_sp-32/4, 1, 3);
|
||||
__builtin_prefetch ((void**)m_sp-32/4, 0, 3);
|
||||
__builtin_prefetch ((void**)m_sp-64/4, 1, 3);
|
||||
__builtin_prefetch ((void**)m_sp-64/4, 0, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free function. Saves the current context in @p from
|
||||
* and restores the context in @p to.
|
||||
* @note This function is found by ADL.
|
||||
*/
|
||||
friend
|
||||
void
|
||||
swap_context(ia32_gcc_context_impl_base& from,
|
||||
ia32_gcc_context_impl_base const& to,
|
||||
default_hint) {
|
||||
to.prefetch();
|
||||
swapcontext_stack(&from.m_sp, to.m_sp);
|
||||
}
|
||||
|
||||
#ifndef BOOST_COROUTINE_NO_SEPARATE_CALL_SITES
|
||||
friend
|
||||
void
|
||||
swap_context(ia32_gcc_context_impl_base& from,
|
||||
ia32_gcc_context_impl_base const& to,
|
||||
yield_hint) {
|
||||
to.prefetch();
|
||||
swapcontext_stack2(&from.m_sp, to.m_sp);
|
||||
}
|
||||
|
||||
friend
|
||||
void
|
||||
swap_context(ia32_gcc_context_impl_base& from,
|
||||
ia32_gcc_context_impl_base const& to,
|
||||
yield_to_hint) {
|
||||
to.prefetch();
|
||||
swapcontext_stack2(&from.m_sp, to.m_sp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void ** m_sp;
|
||||
|
||||
};
|
||||
|
||||
class ia32_gcc_context_impl : public ia32_gcc_context_impl_base{
|
||||
public:
|
||||
enum {default_stack_size = 64*1024};
|
||||
|
||||
typedef ia32_gcc_context_impl_base context_impl_base;
|
||||
|
||||
ia32_gcc_context_impl() :
|
||||
m_stack(0) {}
|
||||
/**
|
||||
* Create a context that on restore invokes Functor on
|
||||
* a new stack. The stack size can be optionally specified.
|
||||
*/
|
||||
template<typename Functor>
|
||||
ia32_gcc_context_impl(Functor& cb, std::ptrdiff_t stack_size = -1) :
|
||||
m_stack_size(stack_size == -1? default_stack_size: stack_size),
|
||||
m_stack(posix::alloc_stack(m_stack_size)) {
|
||||
m_sp = ((void**)m_stack + (m_stack_size/sizeof(void*))),
|
||||
BOOST_ASSERT(m_stack);
|
||||
typedef void fun(Functor*);
|
||||
fun * funp = trampoline;
|
||||
#ifndef BOOST_COROUTINE_INLINE_ASM
|
||||
*--m_sp = &cb; // parm 0 of trampoline;
|
||||
*--m_sp = 0; // dummy return address for trampoline
|
||||
*--m_sp = (void*) funp ;// return addr (here: start addr) NOTE: the unsafe cast is safe on IA32
|
||||
*--m_sp = 0; // ebp
|
||||
*--m_sp = 0; // ebx
|
||||
*--m_sp = 0; // esi
|
||||
*--m_sp = 0; // edi
|
||||
#else
|
||||
*--m_sp = &cb; // parm 0 of trampoline;
|
||||
*--m_sp = 0; // dummy return address for trampoline
|
||||
*--m_sp = (void*) funp ;// return addr (here: start addr) NOTE: the unsafe cast is safe on IA32
|
||||
#endif
|
||||
}
|
||||
|
||||
~ia32_gcc_context_impl() {
|
||||
if(m_stack)
|
||||
posix::free_stack(m_stack, m_stack_size);
|
||||
}
|
||||
|
||||
private:
|
||||
std::ptrdiff_t m_stack_size;
|
||||
void * m_stack;
|
||||
};
|
||||
|
||||
typedef ia32_gcc_context_impl context_impl;
|
||||
}
|
||||
} } }
|
||||
|
||||
#elif defined(__linux)
|
||||
/**
|
||||
* For all other linux systems use the standard posix implementation.
|
||||
*/
|
||||
#include <boost/coroutine/detail/context_posix.hpp>
|
||||
namespace boost { namespace coroutines { namespace detail { namespace oslinux {
|
||||
typedef posix::context_impl context_impl;
|
||||
} } } }
|
||||
#else
|
||||
#error This header can only be included when compiling for linux systems.
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
231
libraries/include/boost/coroutine/detail/context_posix.hpp
Normal file
231
libraries/include/boost/coroutine/detail/context_posix.hpp
Normal file
@@ -0,0 +1,231 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_CONTEXT_POSIX_HPP_20060601
|
||||
#define BOOST_COROUTINE_CONTEXT_POSIX_HPP_20060601
|
||||
|
||||
// NOTE (per http://lists.apple.com/archives/darwin-dev/2008/Jan/msg00232.html):
|
||||
// > Why the bus error? What am I doing wrong?
|
||||
// This is a known issue where getcontext(3) is writing past the end of the
|
||||
// ucontext_t struct when _XOPEN_SOURCE is not defined (rdar://problem/5578699 ).
|
||||
// As a workaround, define _XOPEN_SOURCE before including ucontext.h.
|
||||
#if defined(__APPLE__) && ! defined(_XOPEN_SOURCE)
|
||||
#define _XOPEN_SOURCE
|
||||
// However, the above #define will only affect <ucontext.h> if it has not yet
|
||||
// been #included by something else!
|
||||
#if defined(_STRUCT_UCONTEXT)
|
||||
#error You must #include coroutine headers before anything that #includes <ucontext.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#if defined(_XOPEN_UNIX) && defined(_XOPEN_VERSION) && _XOPEN_VERSION >= 500
|
||||
|
||||
// OS X 10.4 -- despite passing the test above -- doesn't support
|
||||
// swapcontext() et al. Use GNU Pth workalike functions.
|
||||
#if defined(__APPLE__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050)
|
||||
|
||||
#include "pth/pth.h"
|
||||
#include <cerrno>
|
||||
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
namespace posix { namespace pth {
|
||||
inline int check(int rc)
|
||||
{
|
||||
// The makecontext() functions return zero for success, nonzero for
|
||||
// error. The Pth library returns TRUE for success, FALSE for error,
|
||||
// with errno set to the nonzero error in the latter case. Map the Pth
|
||||
// returns to ucontext style.
|
||||
return rc? 0 : errno;
|
||||
}
|
||||
}}}}}
|
||||
|
||||
#define BOOST_CORO_POSIX_IMPL "Pth implementation"
|
||||
#define BOOST_CORO_DECLARE_CONTEXT(name) pth_uctx_t name
|
||||
#define BOOST_CORO_CREATE_CONTEXT(ctx) \
|
||||
boost::coroutines::detail::posix::pth::check(pth_uctx_create(&(ctx)))
|
||||
#define BOOST_CORO_MAKE_CONTEXT(ctx, stack, size, startfunc, startarg, exitto) \
|
||||
/* const sigset_t* sigmask = NULL: we don't expect per-context signal masks */ \
|
||||
boost::coroutines::detail::posix::pth::check(pth_uctx_make(*(ctx), static_cast<char*>(stack), (size), NULL, (startfunc), (startarg), (exitto)))
|
||||
#define BOOST_CORO_SWAP_CONTEXT(from, to) \
|
||||
boost::coroutines::detail::posix::pth::check(pth_uctx_switch(*(from), *(to)))
|
||||
#define BOOST_CORO_DESTROY_CONTEXT(ctx) \
|
||||
boost::coroutines::detail::posix::pth::check(pth_uctx_destroy(ctx))
|
||||
|
||||
#else // generic Posix platform (e.g. OS X >= 10.5)
|
||||
|
||||
/*
|
||||
* makecontext based context implementation. Should be available on all
|
||||
* SuSv2 compliant UNIX systems.
|
||||
* NOTE: this implementation is not
|
||||
* optimal as the makecontext API saves and restore the signal mask.
|
||||
* This requires a system call for every context switch that really kills
|
||||
* performance. Still is very portable and guaranteed to work.
|
||||
* NOTE2: makecontext and friends are declared obsolescent in SuSv3, but
|
||||
* it is unlikely that they will be removed any time soon.
|
||||
*/
|
||||
#include <ucontext.h>
|
||||
#include <cstddef> // ptrdiff_t
|
||||
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
namespace posix { namespace ucontext {
|
||||
inline int make_context(::ucontext_t* ctx, void* stack, std::ptrdiff_t size,
|
||||
void (*startfunc)(void*), void* startarg, ::ucontext_t* exitto = NULL)
|
||||
{
|
||||
int error = ::getcontext(ctx);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
ctx->uc_stack.ss_sp = stack;
|
||||
ctx->uc_stack.ss_size = size;
|
||||
ctx->uc_link = exitto;
|
||||
|
||||
typedef void (*ctx_main)();
|
||||
//makecontext can't fail.
|
||||
::makecontext(ctx,
|
||||
(ctx_main)(startfunc),
|
||||
1,
|
||||
startarg);
|
||||
return 0;
|
||||
}
|
||||
}}}}}
|
||||
|
||||
#define BOOST_CORO_POSIX_IMPL "ucontext implementation"
|
||||
#define BOOST_CORO_DECLARE_CONTEXT(name) ::ucontext_t name
|
||||
#define BOOST_CORO_CREATE_CONTEXT(ctx) /* nop */
|
||||
#define BOOST_CORO_MAKE_CONTEXT(ctx, stack, size, startfunc, startarg, exitto) \
|
||||
boost::coroutines::detail::posix::ucontext::make_context(ctx, stack, size, startfunc, startarg, exitto)
|
||||
#define BOOST_CORO_SWAP_CONTEXT(pfrom, pto) ::swapcontext((pfrom), (pto))
|
||||
#define BOOST_CORO_DESTROY_CONTEXT(ctx) /* nop */
|
||||
|
||||
#endif // generic Posix platform
|
||||
|
||||
#include <signal.h> // SIGSTKSZ
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/coroutine/exception.hpp>
|
||||
#include <boost/coroutine/detail/posix_utility.hpp>
|
||||
#include <boost/coroutine/detail/swap_context.hpp>
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
namespace posix {
|
||||
|
||||
|
||||
/*
|
||||
* Posix implementation for the context_impl_base class.
|
||||
* @note context_impl is not required to be consistent
|
||||
* If not initialized it can only be swapped out, not in
|
||||
* (at that point it will be initialized).
|
||||
*
|
||||
*/
|
||||
class ucontext_context_impl_base {
|
||||
public:
|
||||
ucontext_context_impl_base()
|
||||
{
|
||||
BOOST_CORO_CREATE_CONTEXT(m_ctx);
|
||||
}
|
||||
~ucontext_context_impl_base()
|
||||
{
|
||||
BOOST_CORO_DESTROY_CONTEXT(m_ctx);
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
* Free function. Saves the current context in @p from
|
||||
* and restores the context in @p to.
|
||||
*/
|
||||
friend
|
||||
void
|
||||
swap_context(ucontext_context_impl_base& from,
|
||||
const ucontext_context_impl_base& to,
|
||||
default_hint) {
|
||||
int error = BOOST_CORO_SWAP_CONTEXT(&from.m_ctx, &to.m_ctx);
|
||||
(void)error;
|
||||
BOOST_ASSERT(error == 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
BOOST_CORO_DECLARE_CONTEXT(m_ctx);
|
||||
};
|
||||
|
||||
class ucontext_context_impl :
|
||||
public ucontext_context_impl_base,
|
||||
private boost::noncopyable {
|
||||
public:
|
||||
typedef ucontext_context_impl_base context_impl_base;
|
||||
|
||||
enum {default_stack_size = 64*1024};
|
||||
|
||||
|
||||
/**
|
||||
* Create a context that on restore invokes Functor on
|
||||
* a new stack. The stack size can be optionally specified.
|
||||
*/
|
||||
template<typename Functor>
|
||||
explicit
|
||||
ucontext_context_impl(Functor& cb, std::ptrdiff_t stack_size) :
|
||||
m_stack_size(stack_size == -1? default_stack_size: stack_size),
|
||||
m_stack(alloc_stack(m_stack_size)) {
|
||||
BOOST_ASSERT(m_stack);
|
||||
typedef void cb_type(Functor*);
|
||||
cb_type * cb_ptr = &trampoline<Functor>;
|
||||
int error = BOOST_CORO_MAKE_CONTEXT(&m_ctx, m_stack, m_stack_size,
|
||||
(void (*)(void*))(cb_ptr), &cb, NULL);
|
||||
(void)error;
|
||||
BOOST_ASSERT(error == 0);
|
||||
}
|
||||
|
||||
~ucontext_context_impl() {
|
||||
if(m_stack)
|
||||
free_stack(m_stack, m_stack_size);
|
||||
}
|
||||
|
||||
private:
|
||||
// declare m_stack_size first so we can use it to initialize m_stack
|
||||
std::ptrdiff_t m_stack_size;
|
||||
void * m_stack;
|
||||
};
|
||||
|
||||
typedef ucontext_context_impl context_impl;
|
||||
}
|
||||
} } }
|
||||
#else
|
||||
|
||||
/**
|
||||
* This #else clause is essentially unchanged from the original Google Summer
|
||||
* of Code version of Boost.Coroutine, which comments:
|
||||
* "Context swapping can be implemented on most posix systems lacking *context
|
||||
* using the sigaltstack+longjmp trick."
|
||||
* This is in fact what the (highly portable) Pth library does, so if you
|
||||
* encounter such a system, perhaps the best approach would be to twiddle the
|
||||
* #if logic in this header to use the pth.h implementation above.
|
||||
*/
|
||||
#error No context implementation for this POSIX system.
|
||||
|
||||
#endif
|
||||
#endif
|
||||
181
libraries/include/boost/coroutine/detail/context_windows.hpp
Normal file
181
libraries/include/boost/coroutine/detail/context_windows.hpp
Normal file
@@ -0,0 +1,181 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_CONTEXT_WINDOWS_HPP_20060625
|
||||
#define BOOST_COROUTINE_CONTEXT_WINDOWS_HPP_20060625
|
||||
// This _WIN32_WINNT kludge is necessary to make winbase.h publish the Fiber API.
|
||||
// 0x0400 makes CreateFiber(), etc., visible
|
||||
// 0x0501 makes ConvertThreadToFiber() visible
|
||||
// 0x0600 makes IsThreadAFiber() visible
|
||||
// And no, I have no idea why this symbol isn't being set appropriately by
|
||||
// the build environment.
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define _WIN32_WINNT 0x0600
|
||||
// The above #define will only affect <windows.h> if it has not yet been
|
||||
// #included by something else!
|
||||
#if defined(WINBASEAPI)
|
||||
#error You must #include coroutine headers before anything that #includes <windows.h>
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <winnt.h>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/coroutine/exception.hpp>
|
||||
#include <boost/coroutine/detail/swap_context.hpp>
|
||||
namespace boost {namespace coroutines {namespace detail{
|
||||
namespace windows {
|
||||
|
||||
typedef LPVOID fiber_ptr;
|
||||
|
||||
/*
|
||||
* This number (0x1E00) has been sighted in the wild (at least on windows XP systems)
|
||||
* as return value from GetCurrentFiber() on non fibrous threads. This is sowehow related
|
||||
* to OS/2 where the current fiber pointer is overloaded as a version field.
|
||||
* On non-NT systems, 0 is returned.
|
||||
*/
|
||||
const fiber_ptr fiber_magic = reinterpret_cast<fiber_ptr>(0x1E00);
|
||||
|
||||
/*
|
||||
* Return true if current thread is a fiber.
|
||||
* FIXME: on longhorn shoud use IsThreadAFiber
|
||||
*/
|
||||
inline
|
||||
bool is_fiber() {
|
||||
fiber_ptr current = GetCurrentFiber();
|
||||
return current != 0 && current != fiber_magic;
|
||||
}
|
||||
|
||||
/*
|
||||
* Windows implementation for the context_impl_base class.
|
||||
* @note context_impl is not required to be consistent
|
||||
* If not initialized it can only be swapped out, not in
|
||||
* (at that point it will be initialized).
|
||||
*/
|
||||
class fibers_context_impl_base {
|
||||
public:
|
||||
/**
|
||||
* Create an empty context.
|
||||
* An empty context cannot be restored from,
|
||||
* but can be saved in.
|
||||
*/
|
||||
fibers_context_impl_base() :
|
||||
m_ctx(0) {}
|
||||
|
||||
/*
|
||||
* Free function. Saves the current context in @p from
|
||||
* and restores the context in @p to. On windows the from
|
||||
* parameter is ignored. The current context is saved on the
|
||||
* current fiber.
|
||||
* Note that if the current thread is not a fiber, it will be
|
||||
* converted to fiber on the fly on call and unconverted before
|
||||
* return. This is expensive. The user should convert the
|
||||
* current thread to a fiber once on thread creation for better performance.
|
||||
* Note that we can't leave the thread unconverted on return or else we
|
||||
* will leak resources on thread destruction. Do the right thing by
|
||||
* default.
|
||||
*/
|
||||
friend
|
||||
void
|
||||
swap_context(fibers_context_impl_base& from,
|
||||
const fibers_context_impl_base& to,
|
||||
default_hint) {
|
||||
if(!is_fiber()) {
|
||||
BOOST_ASSERT(from.m_ctx == 0);
|
||||
from.m_ctx = ConvertThreadToFiber(0);
|
||||
BOOST_ASSERT(from.m_ctx != 0);
|
||||
|
||||
SwitchToFiber(to.m_ctx);
|
||||
|
||||
BOOL result = ConvertFiberToThread();
|
||||
BOOST_ASSERT(result);
|
||||
(void)result;
|
||||
from.m_ctx = 0;
|
||||
} else {
|
||||
bool call_from_main = from.m_ctx == 0;
|
||||
if(call_from_main)
|
||||
from.m_ctx = GetCurrentFiber();
|
||||
SwitchToFiber(to.m_ctx);
|
||||
if(call_from_main)
|
||||
from.m_ctx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
~fibers_context_impl_base() {}
|
||||
protected:
|
||||
explicit
|
||||
fibers_context_impl_base(fiber_ptr ctx) :
|
||||
m_ctx(ctx) {}
|
||||
|
||||
fiber_ptr m_ctx;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
VOID CALLBACK
|
||||
trampoline(LPVOID pv) {
|
||||
T* fun = static_cast<T*>(pv);
|
||||
BOOST_ASSERT(fun);
|
||||
(*fun)();
|
||||
}
|
||||
|
||||
class fibers_context_impl :
|
||||
public fibers_context_impl_base,
|
||||
private boost::noncopyable {
|
||||
public:
|
||||
typedef fibers_context_impl_base context_impl_base;
|
||||
|
||||
enum {default_stack_size = 64*1024};
|
||||
|
||||
/**
|
||||
* Create a context that on restore inovkes Functor on
|
||||
* a new stack. The stack size can be optionally specified.
|
||||
*/
|
||||
template<typename Functor>
|
||||
explicit
|
||||
fibers_context_impl(Functor& cb, std::ptrdiff_t stack_size) :
|
||||
fibers_context_impl_base
|
||||
(CreateFiber(stack_size== -1? 0 : stack_size,
|
||||
static_cast<LPFIBER_START_ROUTINE>(&trampoline<Functor>),
|
||||
static_cast<LPVOID>(&cb)))
|
||||
{
|
||||
BOOST_ASSERT(m_ctx);
|
||||
}
|
||||
|
||||
~fibers_context_impl() {
|
||||
DeleteFiber(m_ctx);
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
typedef fibers_context_impl context_impl;
|
||||
|
||||
}
|
||||
} } }
|
||||
#endif
|
||||
103
libraries/include/boost/coroutine/detail/coroutine_accessor.hpp
Normal file
103
libraries/include/boost/coroutine/detail/coroutine_accessor.hpp
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_COROUTINE_ACCESSOR_HPP_20060709
|
||||
#define BOOST_COROUTINE_DETAIL_COROUTINE_ACCESSOR_HPP_20060709
|
||||
#include <boost/utility/in_place_factory.hpp>
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
|
||||
/*
|
||||
* This is a private interface used for coroutine
|
||||
* implementation.
|
||||
*/
|
||||
struct init_from_impl_tag{};
|
||||
struct coroutine_accessor {
|
||||
|
||||
// Initialize coroutine from implementation type.
|
||||
// used by the in_place_assing in place factory.
|
||||
template<typename Coroutine, typename Ctx>
|
||||
static
|
||||
void construct(Ctx * src, void * address) {
|
||||
new (address) Coroutine(src, init_from_impl_tag());
|
||||
}
|
||||
|
||||
template<typename Coroutine>
|
||||
static
|
||||
void acquire(Coroutine& x) {
|
||||
x.acquire();
|
||||
}
|
||||
|
||||
template<typename Coroutine>
|
||||
static
|
||||
void release(Coroutine& x) {
|
||||
x.release();
|
||||
}
|
||||
|
||||
template<typename Ctx>
|
||||
struct in_place_assign : boost::in_place_factory_base {
|
||||
|
||||
in_place_assign(Ctx * ctx) :
|
||||
m_ctx(ctx) {}
|
||||
|
||||
template<typename Coroutine>
|
||||
void apply(void * memory) const {
|
||||
construct<Coroutine>(m_ctx, memory);
|
||||
}
|
||||
Ctx * m_ctx;
|
||||
};
|
||||
|
||||
template<typename Ctx>
|
||||
static
|
||||
in_place_assign<Ctx>
|
||||
in_place(Ctx * ctx) {
|
||||
return in_place_assign<Ctx>(ctx);
|
||||
}
|
||||
|
||||
template<typename Coroutine>
|
||||
static
|
||||
typename Coroutine::impl_ptr
|
||||
get_impl(Coroutine& x) {
|
||||
return x.get_impl();
|
||||
}
|
||||
|
||||
template<typename Coroutine>
|
||||
static
|
||||
typename Coroutine::impl_type *
|
||||
pilfer_impl(Coroutine& x) {
|
||||
return x.pilfer_impl();
|
||||
}
|
||||
|
||||
template<typename Coroutine>
|
||||
static
|
||||
std::size_t
|
||||
count(const Coroutine& x) {
|
||||
return x.count();
|
||||
}
|
||||
};
|
||||
} } }
|
||||
#endif
|
||||
276
libraries/include/boost/coroutine/detail/coroutine_impl.hpp
Normal file
276
libraries/include/boost/coroutine/detail/coroutine_impl.hpp
Normal file
@@ -0,0 +1,276 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_COROUTINE_IMPL_HPP_20060601
|
||||
#define BOOST_COROUTINE_COROUTINE_IMPL_HPP_20060601
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4355) //this used in base member initializer
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/coroutine/detail/argument_unpacker.hpp>
|
||||
#include <boost/coroutine/detail/coroutine_accessor.hpp>
|
||||
#include <boost/coroutine/detail/context_base.hpp>
|
||||
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
|
||||
// This class augment the contest_base class with
|
||||
// the coroutine signature type.
|
||||
// This is mostly just a place to put
|
||||
// typesafe argument and result type pointers.
|
||||
template<typename CoroutineType, typename ContextImpl>
|
||||
class coroutine_impl:
|
||||
public context_base<ContextImpl>
|
||||
{
|
||||
public:
|
||||
template<typename DerivedType, typename ResultType>
|
||||
friend class add_result;
|
||||
|
||||
typedef ContextImpl context_impl;
|
||||
typedef CoroutineType coroutine_type;
|
||||
typedef coroutine_impl<coroutine_type, context_impl> type;
|
||||
typedef context_base<context_impl> context_base;
|
||||
typedef typename coroutine_type::arg_slot_type arg_slot_type;
|
||||
typedef typename coroutine_type::result_type result_type;
|
||||
typedef typename coroutine_type::result_slot_type result_slot_type;
|
||||
|
||||
typedef boost::intrusive_ptr<type> pointer;
|
||||
|
||||
template<typename DerivedType>
|
||||
coroutine_impl(DerivedType * this_, std::ptrdiff_t stack_size) :
|
||||
context_base(*this_, stack_size),
|
||||
m_arg(0),
|
||||
m_result(0){}
|
||||
|
||||
arg_slot_type * args() {
|
||||
BOOST_ASSERT(m_arg);
|
||||
return m_arg;
|
||||
};
|
||||
|
||||
result_slot_type * result() {
|
||||
BOOST_ASSERT(m_result);
|
||||
BOOST_ASSERT(*m_result);
|
||||
return *this->m_result;
|
||||
}
|
||||
|
||||
template<typename Functor>
|
||||
static inline
|
||||
pointer create(Functor, std::ptrdiff_t);
|
||||
|
||||
void bind_args(arg_slot_type* arg) {
|
||||
m_arg = arg;
|
||||
}
|
||||
|
||||
void bind_result(result_slot_type* res) {
|
||||
// This used to be unconditional. But m_result isn't always valid.
|
||||
if (m_result) {
|
||||
*m_result = res;
|
||||
}
|
||||
}
|
||||
|
||||
// Another level of indirecition is needed to handle
|
||||
// yield_to correctly.
|
||||
void bind_result_pointer(result_slot_type** resp) {
|
||||
m_result = resp;
|
||||
}
|
||||
|
||||
result_slot_type** result_pointer() {
|
||||
return m_result;
|
||||
}
|
||||
|
||||
/// This helper class packages data/logic originally found inline in
|
||||
/// coroutine::call_impl() and call_impl_nothrow(), also
|
||||
/// coroutine_impl::run().
|
||||
class local_result_slot_ptr
|
||||
{
|
||||
public:
|
||||
local_result_slot_ptr(pointer pimpl):
|
||||
m_pimpl(pimpl),
|
||||
m_ptr(NULL)
|
||||
{
|
||||
m_pimpl->bind_result_pointer(&m_ptr);
|
||||
}
|
||||
~local_result_slot_ptr()
|
||||
{
|
||||
// In the original use case, a coroutine could only be resumed by
|
||||
// calling coroutine::operator() again, which would rebind the
|
||||
// result pointer to a new valid value. But with the introduction
|
||||
// of futures, it's possible to suspend a coroutine by waiting on
|
||||
// a future object -- thus destroying the local result_slot_type*
|
||||
// -- then resume that coroutine by calling the future's callback,
|
||||
// bypassing coroutine::operator(). This used to leave an old,
|
||||
// invalid result pointer in effect. Subsequent coroutine exit
|
||||
// wrote through that pointer, munging a word of stack. Now we
|
||||
// make a point of setting the bound result pointer NULL when the
|
||||
// result_slot_type* to which it pointed vanishes, so that any
|
||||
// attempt to dereference it will at least self-identify --
|
||||
// instead of producing arbitrary undefined behavior.
|
||||
m_pimpl->bind_result_pointer(NULL);
|
||||
}
|
||||
|
||||
private:
|
||||
pointer m_pimpl;
|
||||
result_slot_type* m_ptr;
|
||||
};
|
||||
|
||||
// This function must be called only for void
|
||||
// coroutines. It wakes up the coroutine.
|
||||
// Entering the wait state does not cause this
|
||||
// method to throw.
|
||||
void run() {
|
||||
arg_slot_type void_args;
|
||||
|
||||
// This dummy binding is required because
|
||||
// do_call expect args() and result()
|
||||
// to return a non NULL result.
|
||||
bind_args(&void_args);
|
||||
local_result_slot_pointer(this);
|
||||
this->wake_up();
|
||||
}
|
||||
protected:
|
||||
boost::optional<result_slot_type> m_result_last;
|
||||
|
||||
private:
|
||||
arg_slot_type * m_arg;
|
||||
result_slot_type ** m_result;
|
||||
|
||||
};
|
||||
|
||||
// This type augment coroutine_impl type with the type of the stored
|
||||
// functor. The type of this object is erased right after construction
|
||||
// when it is assigned to a pointer to coroutine_impl. A deleter is
|
||||
// passed down to make it sure that the correct derived type is deleted.
|
||||
template<typename FunctorType, typename CoroutineType, typename ContextImpl>
|
||||
class coroutine_impl_wrapper :
|
||||
public coroutine_impl<CoroutineType, ContextImpl> {
|
||||
public:
|
||||
typedef coroutine_impl_wrapper<FunctorType, CoroutineType, ContextImpl>
|
||||
type;
|
||||
typedef CoroutineType coroutine_type;
|
||||
typedef typename CoroutineType::result_type result_type;
|
||||
typedef coroutine_impl<CoroutineType, ContextImpl> super_type;
|
||||
|
||||
typedef FunctorType functor_type;
|
||||
coroutine_impl_wrapper(functor_type f, std::ptrdiff_t stack_size) :
|
||||
|
||||
super_type(this, stack_size),
|
||||
m_fun(f){}
|
||||
|
||||
void operator()() {
|
||||
typedef typename super_type::context_exit_status
|
||||
context_exit_status;
|
||||
context_exit_status status = super_type::ctx_exited_return;
|
||||
std::type_info const* tinfo = 0;
|
||||
try {
|
||||
this->check_exit_state();
|
||||
do_call<result_type>();
|
||||
} catch (const exit_exception&) {
|
||||
status = super_type::ctx_exited_exit;
|
||||
} catch (std::exception const& e) {
|
||||
status = super_type::ctx_exited_abnormally;
|
||||
tinfo = &typeid(e);
|
||||
} catch (...) {
|
||||
status = super_type::ctx_exited_abnormally;
|
||||
}
|
||||
this->do_return(status, tinfo);
|
||||
}
|
||||
public:
|
||||
|
||||
//GCC workaround as per enable_if docs
|
||||
template <int> struct dummy { dummy(int) {} };
|
||||
/*
|
||||
* Implementation for operator()
|
||||
* This is for void result types.
|
||||
* Can throw if m_fun throws. At least it can throw exit_exception.
|
||||
*/
|
||||
template<typename ResultType>
|
||||
typename boost::enable_if<boost::is_void<ResultType> >::type
|
||||
do_call(dummy<0> = 0) {
|
||||
BOOST_ASSERT(this->count() > 0);
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
coroutine_type::self self_type;
|
||||
boost::optional<self_type> self (coroutine_accessor::in_place(this));
|
||||
detail::unpack_ex
|
||||
(m_fun,
|
||||
*self,
|
||||
*this->args(),
|
||||
detail::trait_tag<typename coroutine_type::arg_slot_traits>());
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME coroutine_type::result_slot_type
|
||||
result_slot_type;
|
||||
|
||||
// In this particulare case result_slot_type is guaranteed to be
|
||||
// default constructible.
|
||||
this->m_result_last = result_slot_type();
|
||||
this->bind_result(&*this->m_result_last);
|
||||
}
|
||||
|
||||
// Same as above, but for non void result types.
|
||||
template<typename ResultType>
|
||||
typename boost::disable_if<boost::is_void<ResultType> >::type
|
||||
do_call(dummy<1> = 1) {
|
||||
BOOST_ASSERT(this->count() > 0);
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
coroutine_type::self self_type;
|
||||
|
||||
boost::optional<self_type> self (coroutine_accessor::in_place(this));
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME coroutine_type::arg_slot_traits traits;
|
||||
typedef BOOST_DEDUCED_TYPENAME coroutine_type::result_slot_type
|
||||
result_slot_type;
|
||||
|
||||
this->m_result_last = boost::in_place(result_slot_type(detail::unpack_ex
|
||||
(m_fun,
|
||||
*self,
|
||||
*this->args(),
|
||||
detail::trait_tag<traits>())));
|
||||
|
||||
this->bind_result(&*this->m_result_last);
|
||||
}
|
||||
|
||||
FunctorType m_fun;
|
||||
};
|
||||
|
||||
template<typename CoroutineType, typename ContextImpl>
|
||||
template<typename Functor>
|
||||
inline
|
||||
typename
|
||||
coroutine_impl<CoroutineType, ContextImpl>::pointer
|
||||
coroutine_impl<CoroutineType, ContextImpl>::
|
||||
create(Functor f, std::ptrdiff_t stack_size = default_stack_size) {
|
||||
return new coroutine_impl_wrapper<Functor, CoroutineType, ContextImpl>
|
||||
(f, stack_size);
|
||||
}
|
||||
|
||||
} } }
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_COROUTINE_TRAITS_HPP_20060613
|
||||
#define BOOST_COROUTINE_DETAIL_COROUTINE_TRAITS_HPP_20060613
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/coroutine/tuple_traits.hpp>
|
||||
#include <boost/coroutine/detail/yield_result_type.hpp>
|
||||
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
|
||||
template<typename T>
|
||||
struct as_tuple {
|
||||
typedef typename T::as_tuple type;
|
||||
};
|
||||
|
||||
// This trait class is used to compute
|
||||
// all nested typedefs of coroutines given
|
||||
// a signature in the form 'result_type(parm1, ... parmn)'.
|
||||
template<typename Signature>
|
||||
struct coroutine_traits {
|
||||
private:
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::function_traits<Signature>::result_type
|
||||
signature_result_type;
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::mpl::eval_if<is_tuple_traits<signature_result_type>,
|
||||
as_tuple<signature_result_type>,
|
||||
boost::mpl::identity<signature_result_type> >
|
||||
::type result_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::mpl::eval_if<is_tuple_traits<signature_result_type>,
|
||||
boost::mpl::identity<signature_result_type>,
|
||||
boost::mpl::if_
|
||||
<boost::is_same<signature_result_type, void>,
|
||||
tuple_traits<>,
|
||||
tuple_traits<signature_result_type> > >
|
||||
::type result_slot_traits;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME result_slot_traits
|
||||
::as_tuple result_slot_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME detail::make_tuple_traits
|
||||
<typename detail::signature<Signature>::type >
|
||||
::type arg_slot_traits;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME arg_slot_traits
|
||||
::as_tuple arg_slot_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME arg_slot_traits
|
||||
::as_result yield_result_type;
|
||||
|
||||
};
|
||||
} } }
|
||||
#endif
|
||||
@@ -0,0 +1,122 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DEFAULT_CONTEXT_IMPL_HPP_20060601
|
||||
#define BOOST_COROUTINE_DEFAULT_CONTEXT_IMPL_HPP_20060601
|
||||
#include <boost/config.hpp>
|
||||
/*
|
||||
ContextImpl concept documentation.
|
||||
A ContextImpl holds a context plus its stack.
|
||||
- ContextImpl must have constructor with the following signature:
|
||||
|
||||
template<typename Functor>
|
||||
ContextImpl(Functor f, std::ptrdiff_t stack_size);
|
||||
|
||||
Preconditions:
|
||||
f is a generic function object (support for function pointers
|
||||
is not required.
|
||||
stack_size is the size of the stack allocated
|
||||
for the context. The stack_size is only an hint. If stack_size is -1
|
||||
it should default to a sensible value.
|
||||
Postconditions:
|
||||
f is bound to this context in its own stack.
|
||||
When the context is activated with swap_context for the first time
|
||||
f is entered.
|
||||
|
||||
- ContextImpl destructor must properly dispose of the stack and perform
|
||||
any other clean up action required.
|
||||
|
||||
- ContextImpl is not required to be DefaultConstructible nor Copyable.
|
||||
|
||||
- ContextImpl must expose the following typedef:
|
||||
|
||||
typedef unspecified-type context_impl_base;
|
||||
|
||||
ContextImpl must be convertible to context_impl_base.
|
||||
context_impl_base must have conform to the ContextImplBase concept:
|
||||
|
||||
- DefaultConstructible. A default constructed ContextImplBase is in
|
||||
an unitialized state.
|
||||
A ContextImpl is an initialized ContextImplBase.
|
||||
|
||||
- ContextImplBase is Copyable. A copy of a ContextImplBase holds
|
||||
The same informations as the original. Once a ContextImplBase
|
||||
is used as an argument to swap_context, all its copies become stale.
|
||||
(that is, only one copy of ContextImplBase can be used).
|
||||
A ContextImpl cannot be sliced by copying it to a ContextImplBase.
|
||||
|
||||
- void swap_context(ContextImplBase& from,
|
||||
const ContextImplBase& to)
|
||||
|
||||
This free function is called unqualified (via ADL).
|
||||
Preconditions:
|
||||
Its 'to' argument must be an initialized ContextImplBase.
|
||||
Its 'from' argument may be an uninitialized ContextImplBase that
|
||||
will be initialized by a swap_context.
|
||||
Postconditions:
|
||||
The current context is saved in the 'from' context, and the
|
||||
'to' context is restored.
|
||||
It is undefined behaviour if the 'to' argument is an invalid
|
||||
(uninitialized) swapcontext.
|
||||
|
||||
A ContextImplBase is meant to be used when an empty temporary
|
||||
context is needed to store the current context before
|
||||
restoring a ContextImpl and no current context is
|
||||
available. It could be possible to simply have ContextImpl
|
||||
default constructible, but on destruciton it would need to
|
||||
check if a stack has been allocated and would slow down the
|
||||
fast invcation path. Also a stackful context could not be
|
||||
make copiable.
|
||||
*/
|
||||
|
||||
#if defined(__linux) || defined(linux) || defined(__linux__)
|
||||
|
||||
#include <boost/coroutine/detail/context_linux.hpp>
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
typedef oslinux::context_impl default_context_impl;
|
||||
} } }
|
||||
|
||||
#elif defined(_POSIX_VERSION)
|
||||
|
||||
#include <boost/coroutine/detail/context_posix.hpp>
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
typedef posix::context_impl default_context_impl;
|
||||
} } }
|
||||
#elif defined(BOOST_WINDOWS)
|
||||
#include <boost/coroutine/detail/context_windows.hpp>
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
typedef windows::context_impl default_context_impl;
|
||||
} } }
|
||||
|
||||
#else
|
||||
|
||||
#error No default_context_impl available for this system
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
61
libraries/include/boost/coroutine/detail/fix_result.hpp
Normal file
61
libraries/include/boost/coroutine/detail/fix_result.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_FIX_RESULT_HPP_20060709
|
||||
#define BOOST_COROUTINE_DETAIL_FIX_RESULT_HPP_20060709
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
template<typename Traits>
|
||||
inline
|
||||
void
|
||||
fix_result(const typename Traits::as_tuple&,
|
||||
typename
|
||||
boost::enable_if_c<Traits::length == 0>::type * = 0){}
|
||||
|
||||
|
||||
template<typename Traits>
|
||||
inline
|
||||
typename Traits::template at<0>::type
|
||||
fix_result(const typename Traits::as_tuple& x,
|
||||
typename
|
||||
boost::enable_if_c<Traits::length == 1>::type * = 0){
|
||||
using boost::get;
|
||||
return get<0>(x);
|
||||
}
|
||||
|
||||
|
||||
template<typename Traits>
|
||||
inline
|
||||
typename Traits::as_tuple
|
||||
fix_result(const typename Traits::as_tuple& x,
|
||||
typename
|
||||
boost::enable_if_c<(Traits::length > 1)>::type* =0){
|
||||
return x;
|
||||
}
|
||||
} } }
|
||||
#endif
|
||||
140
libraries/include/boost/coroutine/detail/future_impl.hpp
Normal file
140
libraries/include/boost/coroutine/detail/future_impl.hpp
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_FUTURE_IMPL_HPP_20060809
|
||||
#define BOOST_COROUTINE_DETAIL_FUTURE_IMPL_HPP_20060809
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/coroutine/detail/coroutine_accessor.hpp>
|
||||
#include <boost/coroutine/detail/context_base.hpp>
|
||||
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
|
||||
|
||||
template<typename ValueType, typename ContextImpl>
|
||||
class future_impl : boost::noncopyable {
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef
|
||||
context_base<ContextImpl> *
|
||||
context_weak_pointer;
|
||||
|
||||
typedef
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
context_base<ContextImpl>::pointer
|
||||
context_pointer;
|
||||
|
||||
typedef boost::optional<value_type> pointer;
|
||||
|
||||
template<typename CoroutineSelf>
|
||||
future_impl(CoroutineSelf& self) :
|
||||
m_coro_impl_weak(coroutine_accessor::get_impl(self)),
|
||||
m_coro_impl(0),
|
||||
m_waited(false)
|
||||
{}
|
||||
|
||||
value_type&
|
||||
value() {
|
||||
return *m_optional;
|
||||
}
|
||||
|
||||
value_type const&
|
||||
value() const{
|
||||
return *m_optional;
|
||||
}
|
||||
|
||||
pointer&
|
||||
get() {
|
||||
return m_optional;
|
||||
}
|
||||
|
||||
pointer const&
|
||||
get() const{
|
||||
return m_optional;
|
||||
}
|
||||
|
||||
bool pending() {
|
||||
return 0 != m_coro_impl.get();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign(const T& val) {
|
||||
BOOST_ASSERT(pending());
|
||||
context_pointer p = m_coro_impl;
|
||||
m_coro_impl = 0;
|
||||
m_optional = val;
|
||||
p->count_down();
|
||||
if(waited() && p->signal())
|
||||
p->wake_up();
|
||||
}
|
||||
|
||||
void mark_pending() {
|
||||
m_coro_impl = m_coro_impl_weak;
|
||||
m_coro_impl ->count_up();
|
||||
}
|
||||
|
||||
void mark_wait(bool how) {
|
||||
m_waited = how;
|
||||
}
|
||||
|
||||
bool waited() const {
|
||||
return m_waited;
|
||||
}
|
||||
|
||||
context_pointer context() {
|
||||
BOOST_ASSERT(pending());
|
||||
return m_coro_impl;
|
||||
}
|
||||
|
||||
void wait(int n) {
|
||||
m_coro_impl_weak->wait(n);
|
||||
}
|
||||
|
||||
void wait() {
|
||||
if(!pending()) return;
|
||||
mark_wait(true);
|
||||
try {
|
||||
m_coro_impl->wait(1);
|
||||
BOOST_ASSERT(!pending());
|
||||
} catch (...) {
|
||||
mark_wait(false);
|
||||
throw;
|
||||
}
|
||||
mark_wait(false);
|
||||
}
|
||||
|
||||
private:
|
||||
context_weak_pointer m_coro_impl_weak;
|
||||
context_pointer m_coro_impl;
|
||||
bool m_waited;
|
||||
boost::optional<value_type> m_optional;
|
||||
};
|
||||
} } }
|
||||
#endif
|
||||
84
libraries/include/boost/coroutine/detail/has_swap.hpp
Normal file
84
libraries/include/boost/coroutine/detail/has_swap.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
// Copyright David Abrahams 2004. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Slightly modified for inclusion on coroutines/detail library.
|
||||
#ifndef BOOST_COROUTINE_DETAIL_HAS_SWAP_HPP_20060709
|
||||
#define BOOST_COROUTINE_DETAIL_HAS_SWAP_HPP_20060709
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace coroutines {
|
||||
|
||||
|
||||
namespace has_swap_
|
||||
{
|
||||
// any soaks up implicit conversions and makes the following
|
||||
// operator++ less-preferred than any other such operator which
|
||||
// might be found via ADL.
|
||||
struct anything { template <class T> anything(T const&); };
|
||||
struct no_swap
|
||||
{
|
||||
char (& operator,(char) )[2];
|
||||
};
|
||||
no_swap swap(anything,anything);
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4675) // function found through argument dependent lookup -- duh!
|
||||
#endif
|
||||
template <class T>
|
||||
struct has_swap_impl
|
||||
{
|
||||
static T& x;
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, value = sizeof(swap(x,x),'x') == 1);
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
typedef boost::mpl::bool_<has_swap_impl<T>::value> type;
|
||||
#else
|
||||
typedef boost::mpl::bool_<value> type;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
template <class T>
|
||||
struct has_swap
|
||||
: has_swap_::has_swap_impl<T>::type
|
||||
{};
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} }
|
||||
|
||||
#endif // include guard
|
||||
42
libraries/include/boost/coroutine/detail/index.hpp
Normal file
42
libraries/include/boost/coroutine/detail/index.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_INDEX_HPP_20060613
|
||||
#define BOOST_COROUTINE_DETAIL_INDEX_HPP_20060613
|
||||
#include <boost/preprocessor/repetition.hpp>
|
||||
#include <boost/coroutine/detail/arg_max.hpp>
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
/*
|
||||
* Workaround for BOOST_PP_ENUM_BINARY_PARAMS, where a token
|
||||
* can't be createed by appending a number to a '<'.
|
||||
* NOTE: we are really abusing BOOST_PP_ENUM_BINARY_PARAMS,
|
||||
* Should simply use BOOST_PP_ENUM.
|
||||
*/
|
||||
enum {BOOST_PP_ENUM_PARAMS(BOOST_COROUTINE_ARG_MAX, index_)};
|
||||
} } }
|
||||
#endif
|
||||
62
libraries/include/boost/coroutine/detail/is_callable.hpp
Normal file
62
libraries/include/boost/coroutine/detail/is_callable.hpp
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_IS_CALLABLE_HPP_20060601
|
||||
#define BOOST_COROUTINE_DETAIL_IS_CALLABLE_HPP_20060601
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/mpl/logical.hpp>
|
||||
#include <boost/mpl/has_xxx.hpp>
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
template<typename T>
|
||||
struct is_function_pointer :
|
||||
boost::mpl::and_<
|
||||
boost::is_pointer<T>,
|
||||
boost::is_function<typename boost::remove_pointer<T>::type > > {
|
||||
typedef is_function_pointer<T> type;
|
||||
};
|
||||
|
||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type);
|
||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(result);
|
||||
|
||||
template<typename T>
|
||||
struct is_functor :
|
||||
boost::mpl::or_<typename has_result_type<T>::type,
|
||||
typename has_result<T>::type>
|
||||
{
|
||||
typedef is_functor<T> type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_callable : boost::mpl::or_<
|
||||
is_functor<T>,
|
||||
is_function_pointer<T> >::type {
|
||||
typedef is_callable<T> type;
|
||||
};
|
||||
} } }
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_MAKE_TUPLE_TRAITS_HPP_20060609
|
||||
#define BOOST_COROUTINE_DETAIL_MAKE_TUPLE_TRAITS_HPP_20060609
|
||||
#include <boost/preprocessor/repetition.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/coroutine/detail/arg_max.hpp>
|
||||
#include <boost/coroutine/tuple_traits.hpp>
|
||||
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
/*
|
||||
* Given a mpl::vector, returns a nullary metafunction
|
||||
* describing a tuple of all types in the vector.
|
||||
* NOTE this is just wrong because it should work for all mpl
|
||||
* sequences, not just vectors. But it is in detail, so leave it
|
||||
* as is. Eventually it will be replaced by Boost.Fusion.
|
||||
* @p type is a tuple of all types in TypeList.
|
||||
* TypeList is one of mpl::vector0, mpl::vector1, etc.
|
||||
*/
|
||||
template<typename TypeList>
|
||||
struct make_tuple_traits;
|
||||
|
||||
#define BOOST_COROUTINE_MAKE_TUPLE_TRAITS_GENERATOR(z, n, unused) \
|
||||
template<BOOST_PP_ENUM_PARAMS(n, class A)> \
|
||||
struct make_tuple_traits<BOOST_PP_CAT(boost::mpl::vector, n) \
|
||||
<BOOST_PP_ENUM_PARAMS(n, A)> >{ \
|
||||
typedef tuple_traits<BOOST_PP_ENUM_PARAMS(n, A)> type; \
|
||||
}; \
|
||||
/**/
|
||||
|
||||
/**
|
||||
* Generate specializations of make_tuple
|
||||
* @note This could be done more elegantly with a recursive metafunction,
|
||||
* but this is simpler and works well anyway.
|
||||
*/
|
||||
BOOST_PP_REPEAT(BOOST_COROUTINE_ARG_MAX,
|
||||
BOOST_COROUTINE_MAKE_TUPLE_TRAITS_GENERATOR, ~);
|
||||
#undef BOOST_COROUTINE_MAKE_TUPLE_TRAITS_GENERATOR
|
||||
|
||||
} } }
|
||||
#endif
|
||||
68
libraries/include/boost/coroutine/detail/noreturn.hpp
Normal file
68
libraries/include/boost/coroutine/detail/noreturn.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_NORETURN_HPP_20060812
|
||||
#define BOOST_COROUTINE_DETAIL_NORETURN_HPP_20060812
|
||||
/*
|
||||
* The BOOST_COROUTINE_NORETURN macro provides a way to
|
||||
* tell the compiler that a function will not return through
|
||||
* the normal return path (it could return throgh a thrown exception).
|
||||
* This not only provieds a possible optimization hint, but also
|
||||
* prevents the compiler from complaining if a function that call
|
||||
* a noreturn function does not call return itself.
|
||||
*/
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(__GNUC__)
|
||||
|
||||
#if __GNUC_MAJOR__ > 3 || (__GNUC_MAJOR__ == 3 && __GNUC_MINOR__ > 3)
|
||||
#define BOOST_COROUTINE_NORETURN(function) \
|
||||
function __attribute__((__noreturn__)) \
|
||||
/**/
|
||||
#else // gcc 3.3
|
||||
#define BOOST_COROUTINE_NORETURN(function) \
|
||||
function
|
||||
/**/
|
||||
#endif // gcc 3.3
|
||||
|
||||
#elif defined (BOOST_MSVC)
|
||||
|
||||
#define BOOST_COROUTINE_NORETURN(function) \
|
||||
__declspec(noreturn) function \
|
||||
/**/
|
||||
|
||||
#else
|
||||
//just for testing, remove the following error.
|
||||
#error no default
|
||||
#define BOOST_COROUTINE_NORETURN(function) \
|
||||
function
|
||||
/**/
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
161
libraries/include/boost/coroutine/detail/posix_utility.hpp
Normal file
161
libraries/include/boost/coroutine/detail/posix_utility.hpp
Normal file
@@ -0,0 +1,161 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_POSIX_UTILITY_HPP_02012006
|
||||
#define BOOST_COROUTINE_DETAIL_POSIX_UTILITY_HPP_02012006
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(_POSIX_VERSION)
|
||||
/**
|
||||
* Most of these utilities are really pure C++, but they are useful
|
||||
* only on posix systems.
|
||||
*/
|
||||
#include <cerrno>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <boost/type_traits.hpp>
|
||||
#if defined(_POSIX_MAPPED_FILES) && _POSIX_MAPPED_FILES > 0
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
/**
|
||||
* Stack allocation routines and trampolines for setcontext
|
||||
*/
|
||||
namespace boost { namespace coroutines { namespace detail { namespace posix {
|
||||
|
||||
#if defined(_POSIX_MAPPED_FILES) && _POSIX_MAPPED_FILES > 0
|
||||
|
||||
inline
|
||||
void *
|
||||
alloc_stack(std::size_t size) {
|
||||
void * stack = ::mmap(NULL,
|
||||
size,
|
||||
PROT_EXEC|PROT_READ|PROT_WRITE,
|
||||
#if defined(__APPLE__)
|
||||
MAP_PRIVATE|MAP_ANON,
|
||||
#else // ! __APPLE__
|
||||
MAP_PRIVATE|MAP_ANONYMOUS,
|
||||
#endif // ! __APPLE__
|
||||
-1,
|
||||
0
|
||||
);
|
||||
if(stack == MAP_FAILED) {
|
||||
std::cerr <<strerror(errno)<<"\n";
|
||||
abort();
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
inline
|
||||
void free_stack(void* stack, std::size_t size) {
|
||||
::munmap(stack, size);
|
||||
}
|
||||
|
||||
#else // non-mmap()
|
||||
|
||||
//this should be a fine default.
|
||||
static const std::size_t stack_alignment = sizeof(void*) > 16? sizeof(void*): 16;
|
||||
|
||||
struct stack_aligner {
|
||||
boost::type_with_alignment<stack_alignment>::type dummy;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stack allocator and deleter functions.
|
||||
* Better implementations are possible using
|
||||
* mmap (might be required on some systems) and/or
|
||||
* using a pooling allocator.
|
||||
* NOTE: the SuSv3 documentation explictly allows
|
||||
* the use of malloc to allocate stacks for makectx.
|
||||
* We use free for guaranteed alignment.
|
||||
*/
|
||||
inline
|
||||
void* alloc_stack(std::size_t size) {
|
||||
return new stack_aligner[size/sizeof(stack_aligner)];
|
||||
}
|
||||
|
||||
inline
|
||||
void free_stack(void* stack, std::size_t size) {
|
||||
delete [] static_cast<stack_aligner*>(stack);
|
||||
}
|
||||
|
||||
#endif // non-mmap() implementation of alloc_stack()/free_stack()
|
||||
|
||||
/**
|
||||
* The splitter is needed for 64 bit systems.
|
||||
* @note The current implementation does NOT use
|
||||
* (for debug reasons).
|
||||
* Thus it is not 64 bit clean.
|
||||
* Use it for 64 bits systems.
|
||||
*/
|
||||
template<typename T>
|
||||
union splitter {
|
||||
int int_[2];
|
||||
T* ptr;
|
||||
splitter(int first, int second) {
|
||||
int_[0] = first;
|
||||
int_[1] = second;
|
||||
}
|
||||
|
||||
int first() {
|
||||
return int_[0];
|
||||
}
|
||||
|
||||
int second() {
|
||||
return int_[1];
|
||||
}
|
||||
|
||||
splitter(T* ptr) :ptr(ptr) {}
|
||||
|
||||
void operator()() {
|
||||
(*ptr)();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
void
|
||||
trampoline_split(int first, int second) {
|
||||
splitter<T> split(first, second);
|
||||
split();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
void
|
||||
trampoline(T * fun) {
|
||||
(*fun)();
|
||||
}
|
||||
}
|
||||
} } }
|
||||
|
||||
#else
|
||||
#error This header can only be included when compiling for posix systems.
|
||||
#endif
|
||||
|
||||
#endif
|
||||
274
libraries/include/boost/coroutine/detail/self.hpp
Normal file
274
libraries/include/boost/coroutine/detail/self.hpp
Normal file
@@ -0,0 +1,274 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_SELF_HPP_20060809
|
||||
#define BOOST_COROUTINE_DETAIL_SELF_HPP_20060809
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/coroutine/detail/fix_result.hpp>
|
||||
#include <boost/coroutine/detail/coroutine_accessor.hpp>
|
||||
#include <boost/coroutine/detail/signal.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/coroutine/detail/noreturn.hpp>
|
||||
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400))
|
||||
#define BOOST_COROUTINE_DEDUCED_TYPENAME_DEFAULT
|
||||
#else
|
||||
#define BOOST_COROUTINE_DEDUCED_TYPENAME_DEFAULT BOOST_DEDUCED_TYPENAME
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400))
|
||||
#define BOOST_COROUTINE_VCPP80_WORKAROUND
|
||||
#else
|
||||
//for now, define this unconditionally for testing.
|
||||
#define BOOST_COROUTINE_VCPP80_WORKAROUND
|
||||
#endif
|
||||
|
||||
template<typename Coroutine>
|
||||
class coroutine_self :boost::noncopyable {
|
||||
public:
|
||||
typedef Coroutine coroutine_type;
|
||||
typedef coroutine_self<coroutine_type> type;
|
||||
friend struct detail::coroutine_accessor;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME coroutine_type
|
||||
::impl_type impl_type;
|
||||
|
||||
// Note, no reference counting here.
|
||||
typedef impl_type * impl_ptr;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME coroutine_type
|
||||
::result_type result_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME coroutine_type
|
||||
::result_slot_type result_slot_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME coroutine_type
|
||||
::yield_result_type yield_result_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME coroutine_type
|
||||
::result_slot_traits result_slot_traits;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME coroutine_type
|
||||
::arg_slot_type arg_slot_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME coroutine_type
|
||||
::arg_slot_traits arg_slot_traits;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME coroutine_type
|
||||
::yield_traits yield_traits;
|
||||
#ifndef BOOST_COROUTINE_VCPP80_WORKAROUND
|
||||
# define BOOST_COROUTINE_param_with_default(z, n, type_prefix) \
|
||||
BOOST_DEDUCED_TYPENAME call_traits \
|
||||
<BOOST_PP_CAT(BOOST_PP_CAT(type_prefix, n), _type)>::param_type \
|
||||
BOOST_PP_CAT(arg, n) = \
|
||||
BOOST_PP_CAT(BOOST_PP_CAT(type_prefix, n), _type)() \
|
||||
/**/
|
||||
|
||||
yield_result_type yield
|
||||
(BOOST_PP_ENUM
|
||||
(BOOST_COROUTINE_ARG_MAX,
|
||||
BOOST_COROUTINE_param_with_default,
|
||||
BOOST_DEDUCED_TYPENAME yield_traits::arg))
|
||||
{
|
||||
return yield_impl
|
||||
(BOOST_DEDUCED_TYPENAME
|
||||
coroutine_type::result_slot_type
|
||||
(BOOST_PP_ENUM_PARAMS
|
||||
(BOOST_COROUTINE_ARG_MAX,
|
||||
arg)));
|
||||
}
|
||||
|
||||
template<typename Target>
|
||||
yield_result_type yield_to
|
||||
(Target& target
|
||||
BOOST_PP_ENUM_TRAILING
|
||||
(BOOST_COROUTINE_ARG_MAX,
|
||||
BOOST_COROUTINE_param_with_default,
|
||||
typename Target::arg))
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Target::arg_slot_type slot_type;
|
||||
return yield_to_impl
|
||||
(target, slot_type(BOOST_PP_ENUM_PARAMS
|
||||
(BOOST_COROUTINE_ARG_MAX,
|
||||
arg)));
|
||||
}
|
||||
#else
|
||||
|
||||
/*
|
||||
* VC8.0 can't handle the call_traits meta-invocation inside
|
||||
* a function parameter list (except when it does, see operator()).
|
||||
* Splitting it in separate typedefs
|
||||
* fixes the problem.
|
||||
*/
|
||||
#define BOOST_COROUTINE_param_typedef(z, n, prefix_tuple) \
|
||||
typedef BOOST_DEDUCED_TYPENAME \
|
||||
call_traits< \
|
||||
BOOST_PP_CAT \
|
||||
(BOOST_PP_CAT \
|
||||
(BOOST_PP_TUPLE_ELEM(2, 0, prefix_tuple), n), \
|
||||
_type) \
|
||||
>::param_type \
|
||||
BOOST_PP_CAT \
|
||||
(BOOST_PP_CAT \
|
||||
(BOOST_PP_TUPLE_ELEM(2, 1, prefix_tuple), n), \
|
||||
_type) \
|
||||
/**/;
|
||||
|
||||
/*
|
||||
* Generate lines like this:
|
||||
* 'typedef typename call_traits<typename coroutine_type::yield_traits::argN_type>::param_type yield_call_argN_type;'
|
||||
*/
|
||||
BOOST_PP_REPEAT(BOOST_COROUTINE_ARG_MAX,
|
||||
BOOST_COROUTINE_param_typedef,
|
||||
(BOOST_DEDUCED_TYPENAME
|
||||
coroutine_type::yield_traits::arg, yield_call_arg));
|
||||
|
||||
/*
|
||||
* Generate lines like this:
|
||||
* 'typedef typename call_traits<typename coroutine_type::argN_type>::param_type call_argN_type;'
|
||||
*/
|
||||
BOOST_PP_REPEAT(BOOST_COROUTINE_ARG_MAX,
|
||||
BOOST_COROUTINE_param_typedef,
|
||||
(BOOST_DEDUCED_TYPENAME
|
||||
coroutine_type::arg, call_arg));
|
||||
|
||||
#undef BOOST_COROUTINE_param_typedef
|
||||
#undef BOOST_COROUTINE_param_with_default
|
||||
#define BOOST_COROUTINE_param_with_default(z, n, prefix_tuple) \
|
||||
BOOST_PP_CAT(BOOST_PP_CAT \
|
||||
(BOOST_PP_TUPLE_ELEM(2, 0, prefix_tuple), \
|
||||
n), _type) \
|
||||
BOOST_PP_CAT(arg, n) = \
|
||||
BOOST_PP_CAT(BOOST_PP_CAT \
|
||||
(BOOST_PP_TUPLE_ELEM(2, 1, prefix_tuple), \
|
||||
n), _type)() \
|
||||
/**/
|
||||
|
||||
yield_result_type yield
|
||||
(BOOST_PP_ENUM(BOOST_COROUTINE_ARG_MAX,
|
||||
BOOST_COROUTINE_param_with_default,
|
||||
(yield_call_arg ,
|
||||
BOOST_COROUTINE_DEDUCED_TYPENAME_DEFAULT
|
||||
coroutine_type::yield_traits::arg)))
|
||||
{
|
||||
return yield_impl
|
||||
(result_slot_type
|
||||
(BOOST_PP_ENUM_PARAMS(BOOST_COROUTINE_ARG_MAX,arg)));
|
||||
}
|
||||
|
||||
template<typename Target>
|
||||
yield_result_type yield_to
|
||||
(Target& target
|
||||
BOOST_PP_ENUM_TRAILING
|
||||
(BOOST_COROUTINE_ARG_MAX,
|
||||
BOOST_COROUTINE_param_with_default,
|
||||
(BOOST_DEDUCED_TYPENAME Target::self::call_arg,
|
||||
BOOST_COROUTINE_DEDUCED_TYPENAME_DEFAULT Target::arg)))
|
||||
{
|
||||
typedef typename Target::arg_slot_type type;
|
||||
return yield_to_impl
|
||||
(target, type
|
||||
(BOOST_PP_ENUM_PARAMS
|
||||
(BOOST_COROUTINE_ARG_MAX, arg)));
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef BOOST_COROUTINE_param_with_default
|
||||
|
||||
BOOST_COROUTINE_NORETURN(void exit()) {
|
||||
m_pimpl -> exit_self();
|
||||
abort();
|
||||
}
|
||||
|
||||
yield_result_type result() {
|
||||
return detail::fix_result<
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
coroutine_type::arg_slot_traits>(*m_pimpl->args());
|
||||
}
|
||||
|
||||
bool pending() const {
|
||||
BOOST_ASSERT(m_pimpl);
|
||||
return m_pimpl->pending();
|
||||
}
|
||||
|
||||
/// @c true only if this @c self object was created by the passed @a coroutine
|
||||
template <typename SomeCoroutine>
|
||||
bool is_from(const SomeCoroutine& coroutine) const
|
||||
{
|
||||
// get_impl() only accepts non-const ref... a mistake, IMO.
|
||||
return static_cast<void*>(coroutine_accessor::get_impl(const_cast<SomeCoroutine&>(coroutine)).get()) ==
|
||||
static_cast<void*>(m_pimpl);
|
||||
}
|
||||
|
||||
/// opaque token used to correlate this 'self' with its corresponding coroutine
|
||||
void* get_id() const { return m_pimpl; }
|
||||
|
||||
private:
|
||||
coroutine_self(impl_type * pimpl, detail::init_from_impl_tag) :
|
||||
m_pimpl(pimpl) {}
|
||||
|
||||
yield_result_type yield_impl(BOOST_DEDUCED_TYPENAME
|
||||
coroutine_type::result_slot_type result) {
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
coroutine_type::result_slot_type slot_type;
|
||||
|
||||
BOOST_ASSERT(m_pimpl);
|
||||
|
||||
this->m_pimpl->bind_result(&result);
|
||||
this->m_pimpl->yield();
|
||||
return detail::fix_result<
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
coroutine_type::arg_slot_traits>(*m_pimpl->args());
|
||||
}
|
||||
|
||||
template<typename TargetCoroutine>
|
||||
yield_result_type yield_to_impl(TargetCoroutine& target,
|
||||
BOOST_DEDUCED_TYPENAME TargetCoroutine
|
||||
::arg_slot_type args) {
|
||||
BOOST_ASSERT(m_pimpl);
|
||||
|
||||
coroutine_accessor::get_impl(target)->bind_args(&args);
|
||||
coroutine_accessor::get_impl(target)->bind_result_pointer(m_pimpl->result_pointer());
|
||||
|
||||
this->m_pimpl->yield_to(*coroutine_accessor::get_impl(target));
|
||||
|
||||
return detail::fix_result<
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
coroutine_type::arg_slot_traits>(*m_pimpl->args());
|
||||
}
|
||||
|
||||
impl_ptr get_impl() {
|
||||
return m_pimpl;
|
||||
}
|
||||
impl_ptr m_pimpl;
|
||||
};
|
||||
} } }
|
||||
|
||||
#endif
|
||||
67
libraries/include/boost/coroutine/detail/signal.hpp
Normal file
67
libraries/include/boost/coroutine/detail/signal.hpp
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_SIGNAL_HPP_20060728
|
||||
#define BOOST_COROUTINE_DETAIL_SIGNAL_HPP_20060728
|
||||
#include <boost/coroutine/detail/future_impl.hpp>
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
/*
|
||||
* Private interface for coroutine signaling/waiting.
|
||||
* These class is friend of future_impl and
|
||||
* its static members are invoked by asynchronous callback functions.
|
||||
*/
|
||||
struct wait_gateway {
|
||||
template<typename Future>
|
||||
static void wait(Future& f, int n) {
|
||||
f.wait(n);
|
||||
}
|
||||
|
||||
template<typename Future>
|
||||
static
|
||||
bool waited(const Future& f) {
|
||||
return f.waited();
|
||||
}
|
||||
|
||||
template<typename Future>
|
||||
static
|
||||
void mark_wait(Future& f, bool how) {
|
||||
f.mark_wait(how);
|
||||
}
|
||||
|
||||
template<typename Future>
|
||||
static
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
Future::impl_pointer
|
||||
get_impl(Future& f) {
|
||||
return f.m_ptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} } }
|
||||
#endif
|
||||
56
libraries/include/boost/coroutine/detail/signature.hpp
Normal file
56
libraries/include/boost/coroutine/detail/signature.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_SIGNATURE_HPP_20060609
|
||||
#define BOOST_COROUTINE_DETAIL_SIGNATURE_HPP_20060609
|
||||
#include <boost/preprocessor/repetition.hpp>
|
||||
#include <boost/coroutine/detail/arg_max.hpp>
|
||||
namespace boost{ namespace coroutines{ namespace detail{
|
||||
/*
|
||||
* Derived from an mpl::vector describing
|
||||
* 'Function' arguments types.
|
||||
*/
|
||||
template<typename Function>
|
||||
struct signature;
|
||||
|
||||
/*
|
||||
* Generate specializations for the signature trait class.
|
||||
*/
|
||||
#define BOOST_COROUTINE_SIGNATURE_GENERATOR(z, n, unused) \
|
||||
template <class R BOOST_PP_ENUM_TRAILING_PARAMS(n, class A)> \
|
||||
struct signature<R( BOOST_PP_ENUM_PARAMS(n,A) ) > \
|
||||
: boost::mpl::BOOST_PP_CAT(vector,n)< \
|
||||
BOOST_PP_ENUM_PARAMS(n,A) \
|
||||
> {}; \
|
||||
/**/
|
||||
|
||||
|
||||
BOOST_PP_REPEAT(BOOST_COROUTINE_ARG_MAX, BOOST_COROUTINE_SIGNATURE_GENERATOR, ~);
|
||||
#undef BOOST_COROUTINE_SIGNATURE_GENERATOR
|
||||
} } }
|
||||
#endif
|
||||
38
libraries/include/boost/coroutine/detail/swap_context.hpp
Normal file
38
libraries/include/boost/coroutine/detail/swap_context.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_SWAP_CONTEXT_HPP_20060611
|
||||
#define BOOST_COROUTINE_SWAP_CONTEXT_HPP_20060611
|
||||
namespace boost{ namespace coroutines { namespace detail {
|
||||
class default_hint {};
|
||||
class yield_hint: public default_hint {};
|
||||
class yield_to_hint: public default_hint {};
|
||||
class invoke_hint: public default_hint {};
|
||||
|
||||
} } }
|
||||
#endif
|
||||
102
libraries/include/boost/coroutine/detail/wait_impl.hpp
Normal file
102
libraries/include/boost/coroutine/detail/wait_impl.hpp
Normal file
@@ -0,0 +1,102 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_WAIT_IMPL_HPP_20060728
|
||||
#define BOOST_COROUTINE_DETAIL_WAIT_IMPL_HPP_20060728
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/coroutine/detail/signal.hpp>
|
||||
namespace boost { namespace coroutines { namespace detail {
|
||||
|
||||
/*
|
||||
* Inokes mark_wait('how') on the 'Idx'th element of 't'
|
||||
* then calls marker::wait<Idx-1> with the same arguments.
|
||||
* returns the result of marker::wait<Idx-1>(...) plus 1 if
|
||||
* the 'Idx'th.pending() is true or plus 0 otherwise.
|
||||
*
|
||||
*/
|
||||
template<int Idx>
|
||||
struct marker {
|
||||
template<typename Tuple>
|
||||
static int mark(Tuple& t, bool how) {
|
||||
wait_gateway::mark_wait(t.template get<Idx-1>(), how);
|
||||
return marker<Idx -1>::mark(t, how) + (t.template get<Idx-1>().pending()? 1:0);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/* Recursion terminator */
|
||||
template<>
|
||||
struct marker<0> {
|
||||
template<typename Tuple>
|
||||
static int mark(Tuple&, bool) { return 0;}
|
||||
};
|
||||
|
||||
template<typename Tuple>
|
||||
void wait_n(const Tuple& t, int n) {
|
||||
BOOST_STATIC_ASSERT(boost::tuples::length<Tuple>::value);
|
||||
wait_gateway::wait(t.get<0>(), n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for at least one future in 'wt' tuple to be signaled.
|
||||
* If at least one future has been already signaled do not
|
||||
* block but returns immediatley (prevents deadlocks).
|
||||
*/
|
||||
template<typename Tuple>
|
||||
void wait_impl(Tuple wt) {
|
||||
try {
|
||||
if(marker<boost::tuples::length<Tuple>::value>::mark(wt, true) > 0)
|
||||
wait_n(wt, 1);
|
||||
} catch (...) {
|
||||
marker<boost::tuples::length<Tuple>::value>::mark(wt, false);
|
||||
throw;
|
||||
}
|
||||
int res = marker<boost::tuples::length<Tuple>::value>::mark(wt, false);
|
||||
BOOST_ASSERT(res < boost::tuples::length<Tuple>::value);
|
||||
(void)res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for all futures in 'wt' tuple to be signaled.
|
||||
*/
|
||||
template<typename Tuple>
|
||||
void wait_all_impl(Tuple wt) {
|
||||
int res = marker<boost::tuples::length<Tuple>::value>::mark(wt, true);
|
||||
try {
|
||||
wait_n(wt, res);
|
||||
} catch (...) {
|
||||
marker<boost::tuples::length<Tuple>::value>::mark(wt, false);
|
||||
throw;
|
||||
}
|
||||
res = marker<boost::tuples::length<Tuple>::value>::mark(wt, false);
|
||||
BOOST_ASSERT(res == 0);
|
||||
}
|
||||
|
||||
} } }
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2006, Giovanni P. Deretta
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINE_DETAIL_YIELD_RESULT_TYPE_HPP_20060609
|
||||
#define BOOST_COROUTINE_DETAIL_YIELD_RESULT_TYPE_HPP_20060609
|
||||
#include <boost/coroutine/detail/make_tuple_traits.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
namespace boost{ namespace coroutines { namespace detail {
|
||||
/**
|
||||
* Same as make_tuple_traits, but if
|
||||
* @p TypeList is singular, @p type is the single element, and
|
||||
* if TypeList is empty, @p type is @p void.
|
||||
*/
|
||||
template<typename TypeList>
|
||||
struct yield_result_type {
|
||||
typedef typename make_tuple_traits<TypeList>::type type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct yield_result_type <boost::mpl::vector1<T> >{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct yield_result_type <boost::mpl::vector0<> >{
|
||||
typedef void type;
|
||||
};
|
||||
} } }
|
||||
#endif
|
||||
Reference in New Issue
Block a user