update example section

This commit is contained in:
oliver Kowalke 2016-03-22 08:26:37 +01:00
parent cf0b1b2844
commit 35e9dcf0d4
31 changed files with 3 additions and 806 deletions

View File

@ -23,7 +23,7 @@ project boost/coroutine/example
<toolset>gcc,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
<toolset>clang,<segmented-stacks>on:<cxxflags>-fsplit-stack
<toolset>clang,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
<link>static
<link>shared
<threading>multi
;

View File

@ -9,7 +9,6 @@
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/coroutine/all.hpp>
#include <boost/thread.hpp>
int count = 384;
@ -41,13 +40,6 @@ void foo( boost::coroutines::asymmetric_coroutine< void >::pull_type & source)
source();
}
void thread_fn()
{
{
boost::coroutines::asymmetric_coroutine< void >::push_type sink( foo);
sink();
}
}
int main( int argc, char * argv[])
{
@ -61,7 +53,8 @@ int main( int argc, char * argv[])
std::cout << "application might fail" << std::endl;
#endif
boost::thread( thread_fn).join();
boost::coroutines::asymmetric_coroutine< void >::push_type sink( foo);
sink();
std::cout << "Done" << std::endl;

View File

@ -1,48 +0,0 @@
# Boost.Coroutine Library Examples Jamfile
# Copyright Oliver Kowalke 2009.
# 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)
# For more information, see http://www.boost.org/
import common ;
import feature ;
import indirect ;
import modules ;
import os ;
import toolset ;
project boost/coroutine/example
: requirements
<library>/boost/context//boost_context
<library>/boost/coroutine//boost_coroutine
<library>/boost/program_options//boost_program_options
<toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
<toolset>gcc,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
<toolset>clang,<segmented-stacks>on:<cxxflags>-fsplit-stack
<toolset>clang,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
<link>static
<threading>multi
;
exe same_fringe
: same_fringe.cpp
;
exe fibonacci
: fibonacci.cpp
;
exe layout
: layout.cpp
;
exe iterator_range
: iterator_range.cpp
;
exe await_emu
: await_emu.cpp
;

View File

@ -1,199 +0,0 @@
// Copyright Evgeny Panasyuk 2013.
// 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)
// e-mail: E?????[dot]P???????[at]gmail.???
// Full emulation of await feature from C# language in C++ based on Stackful Coroutines from
// Boost.Coroutine library.
// This proof-of-concept shows that exact syntax of await feature can be emulated with help of
// Stackful Coroutines, demonstrating that it is superior mechanism.
// Main aim of this proof-of-concept is to draw attention to Stackful Coroutines.
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
#define BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_RESULT_OF_USE_DECLTYPE
#include <boost/coroutine/asymmetric_coroutine.hpp>
#include <boost/type_traits.hpp>
#include <boost/foreach.hpp>
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <functional>
#include <iostream>
#include <cstddef>
#include <utility>
#include <cstdlib>
#include <memory>
#include <vector>
#include <stack>
#include <queue>
#include <ctime>
using namespace std;
using namespace boost;
// ___________________________________________________________ //
template<typename T>
class concurrent_queue
{
queue<T> q;
boost::mutex m;
boost::condition_variable c;
public:
template<typename U>
void push(U &&u)
{
boost::lock_guard<boost::mutex> l(m);
q.push( boost::forward<U>(u) );
c.notify_one();
}
void pop(T &result)
{
boost::unique_lock<boost::mutex> u(m);
c.wait(u, [&]{return !q.empty();} );
result = std::move_if_noexcept(q.front());
q.pop();
}
};
typedef std::function<void()> Task;
concurrent_queue<Task> main_tasks;
auto finished = false;
void reschedule()
{
this_thread::sleep_for(boost::chrono::milliseconds( rand() % 2000 ));
}
// ___________________________________________________________ //
typedef coroutines::asymmetric_coroutine<void>::pull_type coro_pull;
typedef coroutines::asymmetric_coroutine<void>::push_type coro_push;
struct CurrentCoro
{
std::shared_ptr<coro_pull> coro;
coro_push *caller;
};
/*should be thread_local*/ stack<CurrentCoro> coro_stack;
template<typename F>
auto asynchronous(F f) -> future<decltype(f())>
{
typedef promise<decltype(f())> CoroPromise;
CoroPromise coro_promise;
auto coro_future = coro_promise.get_future();
// It is possible to avoid shared_ptr and use move-semantic,
// but it would require to refuse use of std::function (it requires CopyConstructable),
// and would lead to further complication and is unjustified
// for purposes of this proof-of-concept
CurrentCoro current_coro =
{
make_shared<coro_pull>(std::bind( [f](CoroPromise &coro_promise, coro_push &caller)
{
caller();
coro_stack.top().caller = &caller;
coro_promise.set_value( f() );
}, std::move(coro_promise), placeholders::_1 ))
};
coro_stack.push( std::move(current_coro) );
(*coro_stack.top().coro)();
coro_stack.pop();
#ifdef _MSC_VER
return std::move( coro_future );
#else
return coro_future;
#endif
}
struct Awaiter
{
template<typename Future>
auto operator*(Future &&ft) -> decltype(ft.get())
{
typedef decltype(ft.get()) Result;
typedef typename boost::remove_reference<Future>::type FutureValue;
auto &&current_coro = coro_stack.top();
auto result = ft.then([current_coro](FutureValue ready) -> Result
{
main_tasks.push([current_coro]
{
coro_stack.push(std::move(current_coro));
(*coro_stack.top().coro)();
coro_stack.pop();
});
return ready.get();
});
(*coro_stack.top().caller)();
return result.get();
}
};
#define await Awaiter()*
// ___________________________________________________________ //
void async_user_handler();
int main()
{
srand(time(0));
// Custom scheduling is not required - can be integrated
// to other systems transparently
main_tasks.push([]
{
asynchronous([]
{
return async_user_handler(),
finished = true;
});
});
Task task;
while(!finished)
{
main_tasks.pop(task);
task();
}
cout << "Done" << std::endl;
return EXIT_SUCCESS;
}
// __________________________________________________________________ //
int bar(int i)
{
// await is not limited by "one level" as in C#
auto result = await async([i]{ return reschedule(), i*100; });
return result + i*10;
}
int foo(int i)
{
cout << i << ":\tbegin" << endl;
cout << await async([i]{ return reschedule(), i*10; }) << ":\tbody" << endl;
cout << bar(i) << ":\tend" << endl;
return i*1000;
}
void async_user_handler()
{
vector<future<int>> fs;
for(auto i=0; i!=5; ++i)
fs.push_back( asynchronous([i]{ return foo(i+1); }) );
BOOST_FOREACH(auto &&f, fs)
cout << await f << ":\tafter end" << endl;
}

View File

@ -1,34 +0,0 @@
// Copyright Oliver Kowalke 2009.
// 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 <cstdlib>
#include <iostream>
#include <boost/coroutine/all.hpp>
int main()
{
boost::coroutines::asymmetric_coroutine< int >::pull_type source(
[&]( boost::coroutines::asymmetric_coroutine< int >::push_type & sink) {
int first = 1, second = 1;
sink( first);
sink( second);
for ( int i = 0; i < 8; ++i)
{
int third = first + second;
first = second;
second = third;
sink( third);
}
});
for ( auto i : source)
std::cout << i << " ";
std::cout << "\nDone" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,32 +0,0 @@
// Copyright Oliver Kowalke 2009.
// 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 <cstdlib>
#include <iostream>
#include <boost/coroutine/all.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/iterator_range.hpp>
#include <iostream>
int main()
{
boost::coroutines::asymmetric_coroutine<int>::pull_type c(
[](boost::coroutines::asymmetric_coroutine<int>::push_type& yield) {
for (int i = 0; i < 5; ++i) {
yield(i);
}
});
auto crange = boost::make_iterator_range(boost::begin(c), boost::end(c));
for (auto n : crange) {
std::cout << n << " ";
}
std::cout << "\nDone" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,52 +0,0 @@
// Copyright Nat Goodspeed 2013.
// 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 <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <utility>
#include <boost/coroutine/all.hpp>
struct FinalEOL{
~FinalEOL(){
std::cout << std::endl;
}
};
int main(int argc,char* argv[]){
std::vector<std::string> words{
"peas", "porridge", "hot", "peas",
"porridge", "cold", "peas", "porridge",
"in", "the", "pot", "nine",
"days", "old" };
int num=5,width=15;
boost::coroutines::asymmetric_coroutine<std::string>::push_type writer(
[&](boost::coroutines::asymmetric_coroutine<std::string>::pull_type& in){
// finish the last line when we leave by whatever means
FinalEOL eol;
// pull values from upstream, lay them out 'num' to a line
for (;;){
for(int i=0;i<num;++i){
// when we exhaust the input, stop
if(!in) return;
std::cout << std::setw(width) << in.get();
// now that we've handled this item, advance to next
in();
}
// after 'num' items, line break
std::cout << std::endl;
}
});
std::copy(std::begin(words),std::end(words),boost::begin(writer));
std::cout << "\nDone" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,176 +0,0 @@
// Copyright Nat Goodspeed 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSEstd::placeholders::_1_0.txt or copy at
// http://www.boost.org/LICENSEstd::placeholders::_1_0.txt)
#include <cstddef>
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <string>
#include <utility>
#include <boost/coroutine/all.hpp>
struct node
{
typedef std::shared_ptr< node > ptr_t;
// Each tree node has an optional left subtree, an optional right subtree
// and a value of its own. The value is considered to be between the left
// subtree and the right.
ptr_t left, right;
std::string value;
// construct leaf
node(const std::string& v):
left(),right(),value(v)
{}
// construct nonleaf
node(ptr_t l, const std::string& v, ptr_t r):
left(l),right(r),value(v)
{}
static ptr_t create(const std::string& v)
{
return ptr_t(new node(v));
}
static ptr_t create(ptr_t l, const std::string& v, ptr_t r)
{
return ptr_t(new node(l, v, r));
}
};
node::ptr_t create_left_tree_from(const std::string& root)
{
/* --------
root
/ \
b e
/ \
a c
-------- */
return node::create(
node::create(
node::create("a"),
"b",
node::create("c")),
root,
node::create("e"));
}
node::ptr_t create_right_tree_from(const std::string& root)
{
/* --------
root
/ \
a d
/ \
c e
-------- */
return node::create(
node::create("a"),
root,
node::create(
node::create("c"),
"d",
node::create("e")));
}
// recursively walk the tree, delivering values in order
void traverse(node::ptr_t n, boost::coroutines::asymmetric_coroutine<std::string>::push_type& out)
{
if (n->left)
traverse(n->left,out);
out(n->value);
if (n->right)
traverse(n->right,out);
}
int main()
{
{
node::ptr_t left_d(create_left_tree_from("d"));
boost::coroutines::asymmetric_coroutine<std::string>::pull_type left_d_reader(
[&]( boost::coroutines::asymmetric_coroutine<std::string>::push_type & out) {
traverse(left_d,out);
});
std::cout << "left tree from d:\n";
std::copy(boost::begin(left_d_reader),
boost::end(left_d_reader),
std::ostream_iterator<std::string>(std::cout, " "));
std::cout << std::endl;
node::ptr_t right_b(create_right_tree_from("b"));
boost::coroutines::asymmetric_coroutine<std::string>::pull_type right_b_reader(
[&]( boost::coroutines::asymmetric_coroutine<std::string>::push_type & out) {
traverse(right_b,out);
});
std::cout << "right tree from b:\n";
std::copy(boost::begin(right_b_reader),
boost::end(right_b_reader),
std::ostream_iterator<std::string>(std::cout, " "));
std::cout << std::endl;
node::ptr_t right_x(create_right_tree_from("x"));
boost::coroutines::asymmetric_coroutine<std::string>::pull_type right_x_reader(
[&]( boost::coroutines::asymmetric_coroutine<std::string>::push_type & out) {
traverse(right_x,out);
});
std::cout << "right tree from x:\n";
std::copy(boost::begin(right_x_reader),
boost::end(right_x_reader),
std::ostream_iterator<std::string>(std::cout, " "));
std::cout << std::endl;
}
{
node::ptr_t left_d(create_left_tree_from("d"));
boost::coroutines::asymmetric_coroutine<std::string>::pull_type left_d_reader(
[&]( boost::coroutines::asymmetric_coroutine<std::string>::push_type & out) {
traverse(left_d,out);
});
node::ptr_t right_b(create_right_tree_from("b"));
boost::coroutines::asymmetric_coroutine<std::string>::pull_type right_b_reader(
[&]( boost::coroutines::asymmetric_coroutine<std::string>::push_type & out) {
traverse(right_b,out);
});
std::cout << "left tree from d == right tree from b? "
<< std::boolalpha
<< std::equal(boost::begin(left_d_reader),
boost::end(left_d_reader),
boost::begin(right_b_reader))
<< std::endl;
}
{
node::ptr_t left_d(create_left_tree_from("d"));
boost::coroutines::asymmetric_coroutine<std::string>::pull_type left_d_reader(
[&]( boost::coroutines::asymmetric_coroutine<std::string>::push_type & out) {
traverse(left_d,out);
});
node::ptr_t right_x(create_right_tree_from("x"));
boost::coroutines::asymmetric_coroutine<std::string>::pull_type right_x_reader(
[&]( boost::coroutines::asymmetric_coroutine<std::string>::push_type & out) {
traverse(right_x,out);
});
std::cout << "left tree from d == right tree from x? "
<< std::boolalpha
<< std::equal(boost::begin(left_d_reader),
boost::end(left_d_reader),
boost::begin(right_x_reader))
<< std::endl;
}
std::cout << "Done" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,97 +0,0 @@
// Copyright Oliver Kowalke 2009.
// 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 TREE_H
#define TREE_H
#include <cstddef>
#include <string>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/intrusive_ptr.hpp>
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable:4355)
#endif
struct branch;
struct leaf;
struct visitor
{
virtual ~visitor() {};
virtual void visit( branch & b) = 0;
virtual void visit( leaf & l) = 0;
};
struct node
{
typedef boost::intrusive_ptr< node > ptr_t;
std::size_t use_count;
node() :
use_count( 0)
{}
virtual ~node() {}
virtual void accept( visitor & v) = 0;
friend inline void intrusive_ptr_add_ref( node * p)
{ ++p->use_count; }
friend inline void intrusive_ptr_release( node * p)
{ if ( 0 == --p->use_count) delete p; }
};
struct branch : public node
{
node::ptr_t left;
node::ptr_t right;
static ptr_t create( node::ptr_t left_, node::ptr_t right_)
{ return ptr_t( new branch( left_, right_) ); }
branch( node::ptr_t left_, node::ptr_t right_) :
left( left_), right( right_)
{}
void accept( visitor & v)
{ v.visit( * this); }
};
struct leaf : public node
{
std::string value;
static ptr_t create( std::string const& value_)
{ return ptr_t( new leaf( value_) ); }
leaf( std::string const& value_) :
value( value_)
{}
void accept( visitor & v)
{ v.visit( * this); }
};
inline
bool operator==( leaf const& l, leaf const& r)
{ return l.value == r.value; }
inline
bool operator!=( leaf const& l, leaf const& r)
{ return l.value != r.value; }
#if defined(_MSC_VER)
# pragma warning(pop)
#endif
#endif // TREE_H

View File

@ -1,37 +0,0 @@
# Boost.Coroutine Library Examples Jamfile
# Copyright Oliver Kowalke 2009.
# 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)
# For more information, see http://www.boost.org/
import common ;
import feature ;
import indirect ;
import modules ;
import os ;
import toolset ;
project boost/coroutine/example
: requirements
<library>/boost/context//boost_context
<library>/boost/coroutine//boost_coroutine
<library>/boost/program_options//boost_program_options
<library>/boost/random//boost_random
<toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
<toolset>gcc,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
<toolset>clang,<segmented-stacks>on:<cxxflags>-fsplit-stack
<toolset>clang,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
<link>static
<threading>multi
;
exe simple
: simple.cpp
;
exe merge_arrays
: merge_arrays.cpp
;

View File

@ -1,77 +0,0 @@
// Copyright Keld Helsgaun 2000, Oliver Kowalke 2014.
// 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 <cstdlib>
#include <cstddef>
#include <iostream>
#include <vector>
#include <boost/coroutine/all.hpp>
typedef boost::coroutines::symmetric_coroutine< void > coro_t;
std::vector< int > merge( std::vector< int > const& a, std::vector< int > const& b)
{
std::vector< int > c;
std::size_t idx_a = 0, idx_b = 0;
coro_t::call_type * other_a = 0, * other_b = 0;
coro_t::call_type coro_a(
[&]( coro_t::yield_type & yield) {
while ( idx_a < a.size() )
{
if ( b[idx_b] < a[idx_a])
yield( * other_b);
c.push_back(a[idx_a++]);
}
while ( c.size() < a.size() + b.size())
c.push_back( b[idx_b]);
});
coro_t::call_type coro_b(
[&]( coro_t::yield_type & yield) {
while ( idx_b < b.size() )
{
if ( a[idx_a] < b[idx_b])
yield( * other_a);
c.push_back(b[idx_b++]);
}
while ( c.size() < ( a.size() + b.size() ) )
c.push_back( a[idx_a]);
});
other_a = & coro_a;
other_b = & coro_b;
coro_a();
return c;
}
void print( std::string const& name, std::vector< int > const& v)
{
std::cout << name << " : ";
for ( auto itm : v)
{ std::cout << itm << " "; }
std::cout << "\n";
}
int main( int argc, char * argv[])
{
std::vector< int > a = { 1, 5, 6, 10 };
print( "a", a);
std::vector< int > b = { 2, 4, 7, 8, 9, 13 };
print( "b", b);
std::vector< int > c = merge( a, b);
print( "c", c);
std::cout << "Done" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,44 +0,0 @@
// Copyright Oliver Kowalke 2009.
// 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 <cstdlib>
#include <iostream>
#include <boost/coroutine/all.hpp>
typedef boost::coroutines::symmetric_coroutine< void > coro_t;
int main( int argc, char * argv[])
{
coro_t::call_type * other1 = 0;
coro_t::call_type * other2 = 0;
coro_t::call_type coro1(
[&]( coro_t::yield_type & yield) {
std::cout << "foo1" << std::endl;
yield( * other2);
std::cout << "foo2" << std::endl;
yield( * other2);
std::cout << "foo3" << std::endl;
});
coro_t::call_type coro2(
[&]( coro_t::yield_type & yield) {
std::cout << "bar1" << std::endl;
yield( * other1);
std::cout << "bar2" << std::endl;
yield( * other1);
std::cout << "bar3" << std::endl;
});
other1 = & coro1;
other2 = & coro2;
coro1();
std::cout << "Done" << std::endl;
return EXIT_SUCCESS;
}