2
// Copyright Oliver Kowalke 2009.
3
// Distributed under the Boost Software License, Version 1.0.
4
// (See accompanying file LICENSE_1_0.txt or copy at
5
// http://www.boost.org/LICENSE_1_0.txt)
9
typename Fn, typename StackAllocator, typename Allocator,
13
class coroutine_object< Signature, Fn, StackAllocator, Allocator, Caller, Result, 0 > :
14
private stack_tuple< StackAllocator >,
15
public coroutine_base< Signature >
18
typedef typename Allocator::template rebind<
20
Signature, Fn, StackAllocator, Allocator, Caller, Result, 0
25
typedef stack_tuple< StackAllocator > pbase_type;
26
typedef coroutine_base< Signature > base_type;
31
static void destroy_( allocator_t & alloc, coroutine_object * p)
34
alloc.deallocate( p, 1);
37
coroutine_object( coroutine_object const&);
38
coroutine_object & operator=( coroutine_object const&);
42
holder< Result > * hldr_from(
43
reinterpret_cast< holder< Result > * >(
46
reinterpret_cast< intptr_t >( this),
47
this->preserve_fpu() ) ) );
48
this->callee_ = * hldr_from->ctx;
49
this->result_ = hldr_from->data;
50
if ( this->except_) rethrow_exception( this->except_);
53
void unwind_stack_() BOOST_NOEXCEPT
55
BOOST_ASSERT( ! this->is_complete() );
57
this->flags_ |= flag_unwind_stack;
58
holder< void > hldr_to( & this->caller_, true);
61
reinterpret_cast< intptr_t >( & hldr_to),
62
this->preserve_fpu() );
63
this->flags_ &= ~flag_unwind_stack;
65
BOOST_ASSERT( this->is_complete() );
69
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
70
coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
71
StackAllocator const& stack_alloc,
72
allocator_t const& alloc) :
73
pbase_type( stack_alloc, attr.size),
75
trampoline1< coroutine_object >,
77
stack_unwind == attr.do_unwind,
78
fpu_preserved == attr.preserve_fpu),
79
fn_( forward< Fn >( fn) ),
83
coroutine_object( Fn fn, attributes const& attr,
84
StackAllocator const& stack_alloc,
85
allocator_t const& alloc) :
86
pbase_type( stack_alloc, attr.size),
88
trampoline1< coroutine_object >,
90
stack_unwind == attr.do_unwind,
91
fpu_preserved == attr.preserve_fpu),
96
coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
97
StackAllocator const& stack_alloc,
98
allocator_t const& alloc) :
99
pbase_type( stack_alloc, attr.size),
101
trampoline1< coroutine_object >,
103
stack_unwind == attr.do_unwind,
104
fpu_preserved == attr.preserve_fpu),
112
if ( ! this->is_complete() && this->force_unwind() )
118
coroutine_context callee;
119
coroutine_context caller;
122
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
125
catch ( forced_unwind const&)
128
{ this->except_ = current_exception(); }
129
callee = c.impl_->callee_;
132
this->flags_ |= flag_complete;
133
holder< Result > hldr_to( & caller);
136
reinterpret_cast< intptr_t >( & hldr_to),
137
this->preserve_fpu() );
138
BOOST_ASSERT_MSG( false, "coroutine is complete");
141
void deallocate_object()
142
{ destroy_( alloc_, this); }
147
typename Fn, typename StackAllocator, typename Allocator,
151
class coroutine_object< Signature, reference_wrapper< Fn >, StackAllocator, Allocator, Caller, Result, 0 > :
152
private stack_tuple< StackAllocator >,
153
public coroutine_base< Signature >
156
typedef typename Allocator::template rebind<
158
Signature, Fn, StackAllocator, Allocator, Caller, Result, 0
160
>::other allocator_t;
163
typedef stack_tuple< StackAllocator > pbase_type;
164
typedef coroutine_base< Signature > base_type;
169
static void destroy_( allocator_t & alloc, coroutine_object * p)
172
alloc.deallocate( p, 1);
175
coroutine_object( coroutine_object const&);
176
coroutine_object & operator=( coroutine_object const&);
180
holder< Result > * hldr_from(
181
reinterpret_cast< holder< Result > * >(
184
reinterpret_cast< intptr_t >( this),
185
this->preserve_fpu() ) ) );
186
this->callee_ = * hldr_from->ctx;
187
this->result_ = hldr_from->data;
188
if ( this->except_) rethrow_exception( this->except_);
191
void unwind_stack_() BOOST_NOEXCEPT
193
BOOST_ASSERT( ! this->is_complete() );
195
this->flags_ |= flag_unwind_stack;
196
holder< void > hldr_to( & this->caller_, true);
199
reinterpret_cast< intptr_t >( & hldr_to),
200
this->preserve_fpu() );
201
this->flags_ &= ~flag_unwind_stack;
203
BOOST_ASSERT( this->is_complete() );
207
coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
208
StackAllocator const& stack_alloc,
209
allocator_t const& alloc) :
210
pbase_type( stack_alloc, attr.size),
212
trampoline1< coroutine_object >,
214
stack_unwind == attr.do_unwind,
215
fpu_preserved == attr.preserve_fpu),
222
if ( ! this->is_complete() && this->force_unwind() )
228
coroutine_context callee;
229
coroutine_context caller;
232
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
235
catch ( forced_unwind const&)
238
{ this->except_ = current_exception(); }
239
callee = c.impl_->callee_;
242
this->flags_ |= flag_complete;
243
holder< Result > hldr_to( & caller);
246
reinterpret_cast< intptr_t >( & hldr_to),
247
this->preserve_fpu() );
248
BOOST_ASSERT_MSG( false, "coroutine is complete");
251
void deallocate_object()
252
{ destroy_( alloc_, this); }
257
typename Fn, typename StackAllocator, typename Allocator,
261
class coroutine_object< Signature, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller, Result, 0 > :
262
private stack_tuple< StackAllocator >,
263
public coroutine_base< Signature >
266
typedef typename Allocator::template rebind<
268
Signature, Fn, StackAllocator, Allocator, Caller, Result, 0
270
>::other allocator_t;
273
typedef stack_tuple< StackAllocator > pbase_type;
274
typedef coroutine_base< Signature > base_type;
279
static void destroy_( allocator_t & alloc, coroutine_object * p)
282
alloc.deallocate( p, 1);
285
coroutine_object( coroutine_object const&);
286
coroutine_object & operator=( coroutine_object const&);
290
holder< Result > * hldr_from(
291
reinterpret_cast< holder< Result > * >(
294
reinterpret_cast< intptr_t >( this),
295
this->preserve_fpu() ) ) );
296
this->callee_ = hldr_from->ctx;
297
this->result_ = hldr_from->data;
298
if ( this->except_) rethrow_exception( this->except_);
301
void unwind_stack_() BOOST_NOEXCEPT
303
BOOST_ASSERT( ! this->is_complete() );
305
this->flags_ |= flag_unwind_stack;
306
holder< void > hldr_to( & this->caller_, true);
309
reinterpret_cast< intptr_t >( & hldr_to),
310
this->preserve_fpu() );
311
this->flags_ &= ~flag_unwind_stack;
313
BOOST_ASSERT( this->is_complete() );
317
coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
318
StackAllocator const& stack_alloc,
319
allocator_t const& alloc) :
320
pbase_type( stack_alloc, attr.size),
322
trampoline1< coroutine_object >,
324
stack_unwind == attr.do_unwind,
325
fpu_preserved == attr.preserve_fpu),
332
if ( ! this->is_complete() && this->force_unwind() )
338
coroutine_context callee;
339
coroutine_context caller;
342
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
345
catch ( forced_unwind const&)
348
{ this->except_ = current_exception(); }
349
callee = c.impl_->callee_;
352
this->flags_ |= flag_complete;
353
holder< Result > hldr_to( & caller);
356
reinterpret_cast< intptr_t >( & hldr_to),
357
this->preserve_fpu() );
358
BOOST_ASSERT_MSG( false, "coroutine is complete");
361
void deallocate_object()
362
{ destroy_( alloc_, this); }