2
0
mirror of https://github.com/boostorg/context.git synced 2026-01-19 04:02:17 +00:00

add example for filament

This commit is contained in:
Oliver Kowalke
2019-07-29 09:54:06 +02:00
parent 3df6609ac5
commit 9f13306bb6
2 changed files with 115 additions and 0 deletions

View File

@@ -110,6 +110,10 @@ exe unwind_default
: unwind_default.cpp
;
exe filament
: filament.cpp
;
#exe backtrace
# : backtrace.cpp
# ;

111
example/filament.cpp Normal file
View File

@@ -0,0 +1,111 @@
// Copyright Oliver Kowalke 2019.
// 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)
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <unwind.h>
#include <boost/context/fiber_context.hpp>
namespace ctx = boost::context;
class filament {
private:
std::queue< filament > & q_;
ctx::fiber_context f_;
public:
filament( std::queue< filament > & q) :
q_{ q },
f_{} {
}
template< typename Fn >
filament( std::queue< filament > & q, Fn && fn) :
q_{ q },
f_{ [this,fn=std::forward<Fn>(fn)](ctx::fiber_context &&)->ctx::fiber_context{
fn( [this](){
// deque next filament
filament next = std::move( q_.front() );
q_.pop();
// queue this filament
q_.push( std::move( * this) );
// resume next filament
q_.back().resume_next( next);
});
return {};
}} {
}
~filament() {
if ( f_) {
// unwind the filament's stack
std::move( f_).resume_with( ctx::unwind_fiber);
}
}
filament( filament const&) = delete;
filament & operator=( filament const&) = delete;
filament( filament && other):
q_{ other.q_ },
f_{} {
other.f_.swap( f_);
}
filament & operator=( filament && other) {
if ( this != & other) {
other.q_.swap( q_);
other.f_.swap( f_);
}
return * this;
}
void resume_next( filament & fila) {
std::move( fila.f_).resume_with([this](ctx::fiber_context&& f)->ctx::fiber_context {
// store filament's suspended fiber_context
f_ = std::move( f);
return {};
});
}
};
int main( int argc, char * argv[]) {
std::queue< filament > q;
filament main{ q };
unsigned int count = 3;
filament f1{
q,
[count,&q,&main](std::function<void()> && next){
for ( unsigned int i = 1; i <= count; ++i) {
std::printf("ping\n");
if ( i == count) {
// queue the filament `main` to
// resume it at the end of the loop
q.push( std::move( main) );
}
// resume next filament
next();
}
}};
filament f2{
q,
[count](std::function<void()> && next){
for ( unsigned int i = 1; i <= count; ++i) {
std::printf("pong\n");
// resume next filament
next();
}
}};
// queue filament `f2`
q.push( std::move( f2) );
// resume filament `f1`
main.resume_next( f1);
return EXIT_SUCCESS;
}