$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r85318 - trunk/libs/coroutine/doc
From: oliver.kowalke_at_[hidden]
Date: 2013-08-12 09:23:35
Author: olli
Date: 2013-08-12 09:23:35 EDT (Mon, 12 Aug 2013)
New Revision: 85318
URL: http://svn.boost.org/trac/boost/changeset/85318
Log:
coroutine: add example to documentation
Text files modified: 
   trunk/libs/coroutine/doc/motivation.qbk |   129 ++++++++++++++++++++++++++++++++++++++++
   1 files changed, 129 insertions(+), 0 deletions(-)
Modified: trunk/libs/coroutine/doc/motivation.qbk
==============================================================================
--- trunk/libs/coroutine/doc/motivation.qbk	Mon Aug 12 08:19:29 2013	(r85317)
+++ trunk/libs/coroutine/doc/motivation.qbk	2013-08-12 09:23:35 EDT (Mon, 12 Aug 2013)	(r85318)
@@ -157,6 +157,135 @@
         Done
 
 
+[heading chaining coroutines]
+
+The following example demonstrates how coroutines could be chained.
+
+        typedef boost::coroutines::coroutine<std::string> coro_t;
+
+        // deliver each line of input stream to sink as a separate string
+        void readlines(coro_t::push_type& sink, std::istream& in){
+            std::string line;
+            while(std::getline(in,line))
+                sink(line);
+        }
+
+        void tokenize(coro_t::push_type& sink, coro_t::pull_type& source){
+            // This tokenizer doesn't happen to be stateful: you could reasonably
+            // implement it with a single call to push each new token downstream. But
+            // I've worked with stateful tokenizers, in which the meaning of input
+            // characters depends in part on their position within the input line.
+            BOOST_FOREACH(std::string line, source){
+                std::string::size_type pos = 0;
+                while(pos < line.length()){
+                    if (line[pos] == '"'){
+                        std::string token;
+                        ++pos;              // skip open quote
+                        while (pos < line.length() && line[pos] != '"')
+                            token += line[pos++];
+                        ++pos;              // skip close quote
+                        sink(token);        // pass token downstream
+                    } else if (std::isspace(line[pos])){
+                        ++pos;              // outside quotes, ignore whitespace
+                    } else if (std::isalpha(line[pos])){
+                        std::string token;
+                        while (pos < line.length() && std::isalpha(line[pos]))
+                            token += line[pos++];
+                        sink(token);        // pass token downstream
+                    } else {                // punctuation
+                        sink(std::string(1,line[pos++]));
+                    }
+                }
+            }
+        }
+
+        void only_words(coro_t::push_type& sink,coro_t::pull_type& source){
+            BOOST_FOREACH(std::string token,source){
+                if (!token.empty() && std::isalpha(token[0]))
+                    sink(token);
+            }
+        }
+
+        void trace(coro_t::push_type& sink, coro_t::pull_type& source){
+            BOOST_FOREACH(std::string token,source){
+                std::cout << "trace: '" << token << "'\n";
+                sink(token);
+            }
+        }
+
+        struct FinalEOL{
+            ~FinalEOL(){
+                std::cout << std::endl;
+            }
+        };
+
+        void layout(coro_t::pull_type& source,int num,int width){
+            // 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 (!source) return;
+
+                    std::cout << std::setw(width) << source.get();
+                    // now that we've handled this item, advance to next
+                    source();
+                }
+                // after 'num' items, line break
+                std::cout << std::endl;
+            }
+        }
+
+        // For example purposes, instead of having a separate text file in the
+        // local filesystem, construct an istringstream to read.
+        std::string data(
+            "This is the first line.\n"
+            "This, the second.\n"
+            "The third has \"a phrase\"!\n"
+            );
+
+        {
+            std::cout << "\nfilter:\n";
+            std::istringstream infile(data);
+            coro_t::pull_type reader(boost::bind(readlines, _1, boost::ref(infile)));
+            coro_t::pull_type tokenizer(boost::bind(tokenize, _1, boost::ref(reader)));
+            coro_t::pull_type filter(boost::bind(only_words, _1, boost::ref(tokenizer)));
+            coro_t::pull_type tracer(boost::bind(trace, _1, boost::ref(filter)));
+            BOOST_FOREACH(std::string token,tracer){
+                // just iterate, we're already pulling through tracer
+            }
+        }
+
+        {
+            std::cout << "\nlayout() as coroutine::push_type:\n";
+            std::istringstream infile(data);
+            coro_t::pull_type reader(boost::bind(readlines, _1, boost::ref(infile)));
+            coro_t::pull_type tokenizer(boost::bind(tokenize, _1, boost::ref(reader)));
+            coro_t::pull_type filter(boost::bind(only_words, _1, boost::ref(tokenizer)));
+            coro_t::push_type writer(boost::bind(layout, _1, 5, 15));
+            BOOST_FOREACH(std::string token,filter){
+                writer(token);
+            }
+        }
+
+        {
+            std::cout << "\nfiltering output:\n";
+            std::istringstream infile(data);
+            coro_t::pull_type reader(boost::bind(readlines,_1,boost::ref(infile)));
+            coro_t::pull_type tokenizer(boost::bind(tokenize,_1,boost::ref(reader)));
+            coro_t::push_type writer(boost::bind(layout,_1,5,15));
+            // Because of the symmetry of the API, we can use any of these
+            // chaining functions in a push_type coroutine chain as well.
+            coro_t::push_type filter(boost::bind(only_words,boost::ref(writer),_1));
+            BOOST_FOREACH(std::string token,tokenizer){
+                filter(token);
+            }
+        }
+
+
+
 [heading asynchronous operations with boost.asio]
 
 In the past the code using asio's ['asynchronous operations] was scattered by callbacks.