$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: stipe_at_[hidden]
Date: 2007-08-03 19:29:52
Author: srajko
Date: 2007-08-03 19:29:51 EDT (Fri, 03 Aug 2007)
New Revision: 38432
URL: http://svn.boost.org/trac/boost/changeset/38432
Log:
refactor signal_network to use generic dataflow layer (really complete now)
Added:
   sandbox/SOC/2007/signals/boost/dataflow/connection/consumer_map.hpp   (contents, props changed)
   sandbox/SOC/2007/signals/boost/dataflow/phoenix/component/producer_wrapper.hpp   (contents, props changed)
   sandbox/SOC/2007/signals/boost/dataflow/phoenix/detail/
   sandbox/SOC/2007/signals/boost/dataflow/phoenix/detail/static_function_call.hpp   (contents, props changed)
   sandbox/SOC/2007/signals/boost/dataflow/phoenix/producer_container.hpp   (contents, props changed)
   sandbox/SOC/2007/signals/libs/dataflow/doc/concepts.qbk   (contents, props changed)
   sandbox/SOC/2007/signals/libs/dataflow/doc/phoenix.qbk   (contents, props changed)
   sandbox/SOC/2007/signals/libs/dataflow/doc/signals.qbk   (contents, props changed)
   sandbox/SOC/2007/signals/libs/dataflow/example/edit_distance.cpp   (contents, props changed)
   sandbox/SOC/2007/signals/libs/dataflow/example/simple_example.cpp   (contents, props changed)
Added: sandbox/SOC/2007/signals/boost/dataflow/connection/consumer_map.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/signals/boost/dataflow/connection/consumer_map.hpp	2007-08-03 19:29:51 EDT (Fri, 03 Aug 2007)
@@ -0,0 +1,116 @@
+// Copyright 2007 Stjepan Rajko.
+// 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_DATAFLOW_CONNECTION_CONSUMER_MAP_HPP
+#define BOOST_DATAFLOW_CONNECTION_CONSUMER_MAP_HPP
+
+#include <boost/dataflow/support.hpp>
+
+#include <boost/fusion/algorithm/iteration/for_each.hpp>
+#include <boost/fusion/sequence/container/vector.hpp>
+#include <boost/fusion/sequence/intrinsic/at_key.hpp>
+#include <boost/fusion/sequence/intrinsic/front.hpp>
+#include <boost/fusion/sequence/generation/vector_tie.hpp>
+#include <boost/fusion/sequence/view/zip_view.hpp>
+#include <boost/fusion/support/is_sequence.hpp>
+#include <boost/utility/result_of.hpp>
+#include <boost/mpl/not.hpp>
+
+namespace boost { namespace dataflow {
+
+struct fusion_map_consumer;
+
+template<class T>
+struct consumer_map : public T
+{
+    consumer_map(const T& t) : T(t) {}
+    typedef fusion_map_consumer consumer_category;
+    typedef fusion_map_consumer producer_category;
+};
+
+namespace extension
+{   
+    // component >>= map
+    template<typename ProducerTag, typename ConsumerTag>
+    struct connect_impl<ProducerTag, ConsumerTag,
+        typename boost::enable_if<//boost::mpl::and_<
+            //boost::mpl::not_<boost::is_base_of<fusion_map_consumer, ProducerTag> >,
+            boost::is_base_of<fusion_map_consumer, ConsumerTag>
+        /*>*/ >::type >
+    {
+        template<typename Producer, typename Consumer>
+        struct apply
+        {
+            static void call(const Producer &producer, const Consumer &consumer)
+            {
+                connect(
+                    producer,
+                    boost::fusion::at_key<
+                        typename produced_type_of<Producer>::type
+                    >(consumer));
+            }
+            static void call(const Producer &producer, Consumer &consumer)
+            {
+                connect(
+                    producer,
+                    boost::fusion::at_key<
+                        typename produced_type_of<Producer>::type
+                    >(consumer));
+            }
+            static void call(Producer &producer, const Consumer &consumer)
+            {
+                connect(
+                    producer,
+                    boost::fusion::at_key<
+                        typename produced_type_of<Producer>::type
+                    >(consumer));
+            }
+            static void call(Producer &producer, Consumer &consumer)
+            {
+                connect(
+                    producer,
+                    boost::fusion::at_key<
+                        typename produced_type_of<Producer>::type
+                    >(consumer));
+            } 
+        };
+    };
+    
+    // map >>= component
+    template<typename ProducerTag, typename ConsumerTag>
+        struct connect_impl<ProducerTag, ConsumerTag,
+            typename boost::enable_if<//boost::mpl::and_<
+                boost::is_base_of<fusion_map_consumer, ProducerTag>//,
+                //boost::mpl::not_<boost::is_base_of<fusion_group_consumer, ConsumerTag> >
+        /*>*/ >::type >
+    {
+        template<typename Producer, typename Consumer>
+        struct apply
+        {
+            static void call(const Producer &producer, const Consumer &consumer)
+            {
+                connect(boost::fusion::front(producer).second, consumer);
+            }
+            static void call(const Producer &producer, Consumer &consumer)
+            {
+                connect(boost::fusion::front(producer).second, consumer);
+            }
+            static void call(Producer &producer, const Consumer &consumer)
+            {
+                connect(boost::fusion::front(producer).second, consumer);
+            }
+            static void call(Producer &producer, Consumer &consumer)
+            {
+                connect(boost::fusion::front(producer).second, consumer);
+            }
+        };
+    };
+}
+    
+} } // namespace boost::dataflow
+
+#endif // BOOST_DATAFLOW_CONNECTION_CONSUMER_MAP_HPP
+
+
Added: sandbox/SOC/2007/signals/boost/dataflow/phoenix/component/producer_wrapper.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/signals/boost/dataflow/phoenix/component/producer_wrapper.hpp	2007-08-03 19:29:51 EDT (Fri, 03 Aug 2007)
@@ -0,0 +1,64 @@
+// Copyright 2007 Stjepan Rajko.
+// 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_DATAFLOW_PHOENIX_COMPONENT_PRODUCER_WRAPPER_HPP
+#define BOOST_DATAFLOW_PHOENIX_COMPONENT_PRODUCER_WRAPPER_HPP
+
+#include <boost/dataflow/phoenix/support.hpp>
+
+namespace boost { namespace phoenix {
+    
+template<typename T, typename Function> 
+class producer_wrapper
+{
+public:
+    typedef boost::dataflow::phoenix_producer producer_category;
+    typedef T produced_type;
+    typedef T value_type;
+    
+    producer_wrapper(T &value) : value(value) {}
+    
+    void operator()()
+    {
+        value = Function()();
+    }
+    
+    template<typename T1>
+    void operator()(T1 &t1)
+    {
+        value = Function()(t1);
+    }
+    
+    template<typename T1, typename T2>
+    void operator()(T1 &t1, T2 &t2)
+    {
+            value = Function()(t1, t2);
+    }
+    
+    template<typename T1, typename T2, typename T3>
+    void operator()(T1 &t1, T2 &t2, T3 &t3)
+    {
+            value = Function()(t1, t2, t3);
+    }
+
+    T &value;
+};
+
+template<typename T, typename F>
+producer_wrapper<T, F> wrap_producer(T &t, const F &f)
+{
+    return producer_wrapper<T, F>(t);
+}
+
+template<typename F, typename T>
+producer_wrapper<T, F> wrap_producer(T &t)
+{
+    return producer_wrapper<T, F>(t);
+}
+
+} } // namespace boost::phoenix
+
+#endif // BOOST_DATAFLOW_PHOENIX_COMPONENT_PRODUCER_WRAPPER_HPP
+
Added: sandbox/SOC/2007/signals/boost/dataflow/phoenix/detail/static_function_call.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/signals/boost/dataflow/phoenix/detail/static_function_call.hpp	2007-08-03 19:29:51 EDT (Fri, 03 Aug 2007)
@@ -0,0 +1,43 @@
+/*=============================================================================
+Copyright 2007 Stjepan Rajko
+Copyright (c) 2001-2007 Joel de Guzman
+
+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_PP_IS_ITERATING
+#ifndef PHOENIX_FUNCTION_DETAIL_STATIC_FUNCTION_CALL_HPP
+#define PHOENIX_FUNCTION_DETAIL_STATIC_FUNCTION_CALL_HPP
+
+#include <boost/preprocessor/iterate.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+
+#define BOOST_PP_ITERATION_PARAMS_1                                             \
+    (3, (3, BOOST_PP_DEC(PHOENIX_COMPOSITE_LIMIT),                              \
+     <boost/dataflow/phoenix/detail/static_function_call.hpp>))
+#include BOOST_PP_ITERATE()
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+//
+//  Preprocessor vertical repetition code
+//
+///////////////////////////////////////////////////////////////////////////////
+#else // defined(BOOST_PP_IS_ITERATING)
+
+#define N BOOST_PP_ITERATION()
+
+template <BOOST_PP_ENUM_PARAMS(N, typename A)>
+actor<typename as_composite<detail::function_eval<N>, actor<static_value<F> >
+, BOOST_PP_ENUM_PARAMS(N, A)>::type>
+operator()(BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& _)) const
+{
+    return compose<detail::function_eval<N> >(actor<static_value<F> >(), BOOST_PP_ENUM_PARAMS(N, _));
+}
+
+#undef N
+#endif // defined(BOOST_PP_IS_ITERATING)
+
+
Added: sandbox/SOC/2007/signals/boost/dataflow/phoenix/producer_container.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/signals/boost/dataflow/phoenix/producer_container.hpp	2007-08-03 19:29:51 EDT (Fri, 03 Aug 2007)
@@ -0,0 +1,141 @@
+// Copyright 2007 Stjepan Rajko.
+// 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_DATAFLOW_PHOENIX_COMPONENT_PRODUCER_CONTAINER_HPP
+#define BOOST_DATAFLOW_PHOENIX_COMPONENT_PRODUCER_CONTAINER_HPP
+
+#include <boost/dataflow/phoenix/component/producer_wrapper.hpp>
+
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/zip_iterator.hpp>
+#include <boost/mpl/for_each.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/fusion/sequence/adapted/boost_tuple.hpp>
+#include <boost/fusion/sequence/view/joint_view.hpp>
+
+namespace boost { namespace phoenix {
+    
+namespace detail
+{
+    template<typename Iterator>
+    struct applicator_incrementer
+    {
+        applicator_incrementer(Iterator &it) : it(it) {}
+        
+        template<typename F>
+        void operator()(F t)
+        {
+            wrap_producer<F>(*it)(it);
+            it++;
+        }
+        
+        Iterator ⁢
+    };
+    
+    template<typename Iterator, typename Iterator2>
+    struct applicator_incrementer2
+    {
+        applicator_incrementer2(Iterator &it, Iterator2 &it2) : it(it), it2(it2) {}
+        
+        template<typename F>
+        void operator()(F f)
+        {
+            wrap_producer<F>(*it)(it, it2);
+            it++;
+            it2++;
+        }
+        
+        Iterator ⁢
+        Iterator2 &it2;
+    };
+    
+    template<typename Iterator, typename Iterator2, typename Iterator3>
+    struct applicator_incrementer3
+    {
+        applicator_incrementer3(Iterator &it, Iterator2 &it2, Iterator3 &it3) : it(it), it2(it2), it3(it3) {}
+        
+        template<typename F>
+        void operator()(F f)
+        {
+            wrap_producer<F>(*it)(it, it2, it3);
+            it++;
+            it2++;
+            it3++;
+        }
+        
+        Iterator ⁢
+        Iterator2 &it2;
+        Iterator2 &it3;
+    };
+    
+}
+
+template<typename Container, typename F, typename FFirst = mpl::vector0<> >
+class producer_container : public Container
+{
+public:
+    struct eval_iterator : public boost::iterator_adaptor<
+        typename producer_container<Container,F,FFirst>::eval_iterator,
+        typename Container::iterator>
+    {
+        eval_iterator() {}
+        explicit eval_iterator(const typename Container::iterator &i)
+        : eval_iterator::iterator_adaptor_(i) {}
+        
+        typename eval_iterator::reference dereference() const
+        {
+            typename Container::iterator it = this->base_reference();
+            wrap_producer<F>(*it)(it);
+            return *it;
+        }
+
+    private:
+        friend class boost::iterator_core_access;
+    };
+    
+    producer_container() {}
+    
+    template<typename T1>
+    producer_container(const T1& t1) : Container(t1) {}
+    
+    eval_iterator eval_begin() { return eval_iterator(Container::begin()); }
+    eval_iterator eval_end() { return eval_iterator(Container::end()); }
+    
+    void eval()
+    {
+        typename Container::iterator it=Container::begin();
+        boost::mpl::for_each<FFirst>(detail::applicator_incrementer<typename Container::iterator>(it));
+        for ( ; it!=Container::end(); it++)
+            wrap_producer<F>(*it)(it);
+    }
+    template<typename Container2>
+    void eval(Container2 &c2)
+    {
+        typename Container::iterator it=Container::begin();
+        typename Container2::iterator it2=c2.begin();
+
+        boost::mpl::for_each<FFirst>(detail::applicator_incrementer2<typename Container::iterator, typename Container2::iterator>(it, it2));
+        for ( ; it!=Container::end(); it++, it2++)
+            wrap_producer<F>(*it)(it, it2);
+    }
+    template<typename Container2, typename Container3>
+    void eval(Container2 &c2, Container3 &c3)
+    {
+            typename Container::iterator it=Container::begin();
+            typename Container2::iterator it2=c2.begin();
+            typename Container3::iterator it3=c3.begin();
+            
+            boost::mpl::for_each<FFirst>(detail::applicator_incrementer3<
+                typename Container::iterator,
+                typename Container2::iterator,
+                typename Container3::iterator >(it, it2, it3));
+            for ( ; it!=Container::end(); it++, it2++, it3++)
+                wrap_producer<F>(*it)(it, it2, it3);
+    }
+};
+
+} } // namespace boost::phoenix
+
+#endif // BOOST_DATAFLOW_PHOENIX_COMPONENT_PRODUCER_WRAPPER_HPP
\ No newline at end of file
Added: sandbox/SOC/2007/signals/libs/dataflow/doc/concepts.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/signals/libs/dataflow/doc/concepts.qbk	2007-08-03 19:29:51 EDT (Fri, 03 Aug 2007)
@@ -0,0 +1,323 @@
+[section Concepts]
+
+To explore generic dataflow in C++, let us begin by examining where the flow of
+data happens in C++.  Rather informally, we can divide things as follows:
+
+* on one hand, there is data (variables, objects, etc...)
+* on the other, there are computational elements (functions, methods, etc...)
+
+Data can then be processed by the computational
+elements by applying the elements to the data in some appropriate way.
+There are several ways of providing data to the computational elements:
+
+* by placing it in a location where the computational element will read it
+* by passing it as a parameter in a call
+* (a combination of the above) by passing the location of the data as a
+parameter in a call
+
+Similarly, there are several ways of getting data out of a computational element:
+
+* the element makes a function call that carries the data as a parameter
+* the element places a value somewhere where it can be read
+* the element returns it as a return value
+
+With the above in mind, let's informally introduce a few concepts related to dataflow
+programming:
+
+[heading Components]
+
+We will call the fundamental processing elements of a dataflow program
+/components/, which have two categories:
+
+* /producers/, which produce data; and
+* /consumers/, which consume data.
+
+Depending on the data-transport mechanism used, a producer could be anything
+that produces / provides data:  a POD variable, an object of a class type, or
+a function that returns a value.  Similarly, a consumer could be anything
+that consumes data - a function that takes an argument, a functor, etc.
+
+Producers and consumers are captured more formally by the [ProducerConcept]
+and [ConsumerConcept] concepts.
+
+[heading Connections]
+
+To establish a flow of data in a dataflow program, we typically /connect/
+producers and consumers using some type of /connection/. In C++, this is usually
+done through a pointer-like mechanism.  For example, a boost::signal can be used
+by a producer to dissiminate data to multiple consumers which have been
+connected to the signal. Or, a consumer class might have a pointer to a variable
+which it collects data from.
+
+Connectability is captured more formally by the [ConnectableConcept] concept.
+
+[/
+[heading Push and pull]
+
+Components can be further categorized according to where the connection lies,
+and what it points to.  If the producer contains the connection(s) which point
+to the consumer(s) (say, a `boost::signal<void (int)>`), the producer is called a
+/push producer/.  If the consumer contains the connection(s) which point to the
+producer(s), the consumer is called a /pull consumer/.  A connection
+between a push producer and a (non-pull) consumer is a /push connection/,
+and a connection between a pull consumer and a (non-push) producer is a
+/pull connection/.
+
+Sometimes things get a little fuzzy - for example, a function
+call can be used to transmit data through the arguments from the caller to the
+callee.  However, the callee can transmit data back to the caller by returning
+it.  Hence, an object which contains a boost::signal could be both a push
+producer (which sends data through the signal argument) and a pull consumer
+(which receives data through the signal return type).  If both directions
+are being used to transmit data, a connection like this is called a /push and
+pull connection/.
+
+It is also possible that the producer points to the consumer and vice versa.
+In this case, the connection is called a /bidirectional connection/.]
+
+[heading Invocation]
+
+Another important thing to note is that there is a separation between providing
+the data to a component, and invoking the component.  In some cases, the two
+happen simoultaneously (when the data is passed and returned via a function
+call), while in others invoking the computational element can happen
+separately from providing the data (at least from a modeling perspective).
+An example of the latter is a consumer which uses data stored in
+a particular location. We can place the data in that location much before
+invoking the consumer.
+
+We will call /invoking/ a component (producer or consumer) the action of
+causing it to consume data from connected producers, and producing data
+for connected consumers.
+
+Invocation is captured more formally by the [InvocableConcept] concept.
+
+[/An invocation is /forwarding/
+if it causes the invoked producer to also invoke the consumer, or if it causes
+the invoked consumer to invoke the producer.]
+
+[section Producer]
+
+A type `P` is a ['[ProducerConcept]] if it defines a producer category, 
+a produced type, and specifies whether it is invocable.
+To be useful, a [ProducerConcept] should likely be
+[ConnectableConcept] to at least one [ConsumerConcept].  Also, at least
+one component of a connected network should be [InvocableConcept].
+
+[heading Refinements]
+* [PhoenixProducerConcept]
+
+[heading Notation]
+The following expressions are used in this document:
+
+[variablelist
+    [[P] [A Producer type.]]
+]
+
+[heading Requirements]
+[table
+    [[Name] [Expression] [Result Type] [Description]]
+    [
+        [Producer Category]
+        [`producer_category_of<P>::type`
+         [footnote `namespace boost::dataflow`]]
+        [Any type]
+        [
+            *Semantics:* The category of the producer, used for tag forwarding.
+        ]
+    ]
+    [
+        [Produced Type]
+        [`produced_type_of<P>::type`
+         [footnote `namespace boost::dataflow`]]
+        [Any type]
+        [
+            *Semantics:* The type of data produced by the producer.
+            [footnote This might
+            mean different things for different producer categories - for
+            example, a SignalProducer uses function types, whereas
+            a PhoenixProducer uses object types.].
+        ]
+    ]
+    [
+        [Producer Trait]
+        [`is_producer<P>::type`
+         [footnote `namespace boost::dataflow`]]
+        [mpl::true_ or boost::true_type]
+        [
+            *Semantics:* A trait encapsulating adherence to the Producer
+            concept.
+        ]
+    ]
+    [
+        [Invocable]
+        [`is_invocable<P>::type`
+         [footnote `namespace boost::dataflow`]]
+        [Boolean metafunction]
+        [
+            *Semantics:* A producer must specify if it is [InvocableConcept].
+        ]
+    ]
+]
+
+[heading Notes]
+
+To define a new [ProducerConcept] class type, it is sufficient to define
+member typedefs `producer_category` and `produced_type`.
+
+[heading Examples]
+
+[endsect][/producer]
+
+[section Consumer]
+
+A type `T` is a /consumer/ if it defines a consumer category.
+To be useful, a [ConsumerConcept] should likely be
+[ConnectableConcept] to at least one [ProducerConcept].  Also, at least
+one component of a connected network should be [InvocableConcept].
+
+[heading Refinements]
+* [PhoenixConsumerConcept]
+
+[heading Notation]
+The following expressions are used in this document:
+
+[variablelist
+    [[C] [A Consumer type.]]
+]
+
+[heading Requirements]
+[table
+    [[Name] [Expression] [Result Type] [Description]]
+    [
+        [Consumer Category]
+        [`consumer_category_of<C>::type`
+         [footnote `namespace boost::dataflow`]]
+        [Any type]
+        [
+            *Semantics:* The category of the producer, used for tag forwarding.
+        ]
+    ]
+    [
+        [Consumer Trait]
+        [`is_consumer<C>::type`
+         [footnote `namespace boost::dataflow`]]
+        [mpl::true_ or boost::true_type]
+        [
+            *Semantics:* A trait encapsulating adherence to the Producer
+            concept.
+        ]
+    ]
+[/    [
+        [Consumed Types]
+        [`consumed_types_of<P>::type`]
+        [`mpl::set<any-type-list>`]
+        [
+            *Semantics:* The types of data consumed by the consumer.
+            [footnote The types inside the `mpl::set` might
+            mean different things for different consumer categories - for
+            example, a SignalProducer uses function types, whereas
+            a PhoenixProducer uses object types.].
+        ]
+    ] ]
+]
+
+[heading Notes]
+
+To define a new [ConsumerConcept] class type, it is sufficient to define
+member typedefs `consumer_category` and `consumed_types`.
+
+[heading Examples]
+
+[endsect][/consumer]
+
+[section Invocable]
+
+A type `T` is /invocable/ if it can be invoked to consume its inputs and/or
+produce its outputs.
+
+[heading Notation]
+The following expressions are used in this document:
+
+[variablelist
+    [[C] [An [InvocableConcept] type.]]
+    [[c] [An object of type `P`.]]
+]
+
+[heading Requirements]
+[table
+    [[Name] [Expression] [Result Type] [Description]]
+    [
+        [Invocation]
+        [`invoke(c)`
+         [footnote `namespace boost::dataflow`,
+         `namespace boost::signals`, `namespace boost::phoenix`]]
+        [Any type]
+        [
+            *Semantics:* The component consumes data from connected producers,
+            and makes produced data available to connected consumers.
+            [footnote: This does not imply that it invokes any connected
+            producers or consumers.].
+        ]
+    ]
+    [
+        [Invocable]
+        [`is_invocable<P>::type`
+         [footnote `namespace boost::dataflow`]]
+        [mpl::true_ or boost::true_type]
+        [
+            *Semantics:* A trait encapsulating adherence to the
+            [InvocableConcept] concept.
+        ]
+    ]
+]
+
+[endsect][/invocable]
+
+[section Connectable]
+
+A [ProducerConcept] `P` and [ConsumerConcept] `C` are /connectable/ if they
+can be connected via the `connect` function.  Typically, this means that
+they use the same underlying data transport mechanism, and produce / consume
+the same data type.
+
+[heading Notation]
+The following expressions are used in this document:
+
+[variablelist
+    [[P] [A [ProducerConcept] type.]]
+    [[C] [A [ConsumerConcept] type.
+     [footnote `P` and `C` are [ConnectableConcept]]
+    [[p] [An object of type P.]]
+    [[c] [An object of type C.]]
+]
+
+[heading Requirements]
+[table
+    [[Name] [Expression] [Result Type] [Description]]
+    [
+        [Connect]
+        [`connect(p,c)`]
+        [Any type]
+        [
+            *Semantics:* Creates a permanent connection between the producer
+            and consumer.
+            [footnote: This does not (yet) specify what happens to other
+            existing connections out of `p` of into `c`.  They may or may
+            not get modified of erased.].
+        ]
+    ]
+[/    [
+        [Compatible]
+        [`mpl::has_key<consumed_types_of<C>::type, produced_type_of<P>::type>`]
+        [`mpl::true_`]
+        [
+            *Semantics:* In order for two components to be connectable,
+            the produced type must be an element of the consumed types.
+        ]
+    ] ]
+]
+
+[endsect][/connectable]
+
+[endsect][/concepts]
\ No newline at end of file
Added: sandbox/SOC/2007/signals/libs/dataflow/doc/phoenix.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/signals/libs/dataflow/doc/phoenix.qbk	2007-08-03 19:29:51 EDT (Fri, 03 Aug 2007)
@@ -0,0 +1,5 @@
+[section Dataflow.Phoenix]
+
+[include phoenix/concepts.qbk]
+
+[endsect]
\ No newline at end of file
Added: sandbox/SOC/2007/signals/libs/dataflow/doc/signals.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/signals/libs/dataflow/doc/signals.qbk	2007-08-03 19:29:51 EDT (Fri, 03 Aug 2007)
@@ -0,0 +1,11 @@
+[section:signals Dataflow.Signals]
+
+[include signals/introduction.qbk]
+
+[include signals/concepts.qbk]
+
+[include connections.qbk]
+
+[include components.qbk]
+
+[endsect]
Added: sandbox/SOC/2007/signals/libs/dataflow/example/edit_distance.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/signals/libs/dataflow/example/edit_distance.cpp	2007-08-03 19:29:51 EDT (Fri, 03 Aug 2007)
@@ -0,0 +1,130 @@
+// Copyright 2007 Stjepan Rajko.
+// 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)
+
+
+//[ edit_distance_example
+#include <boost/dataflow/phoenix/producer_container.hpp>
+#include <boost/dataflow/phoenix/connection/iterator_relative.hpp>
+#include <boost/dataflow/phoenix/components.hpp>
+#include <boost/dataflow/phoenix/static_function.hpp>
+
+#include <iostream>
+#include <boost/array.hpp>
+#include <boost/fusion/sequence/generation/make_vector.hpp>
+#include <boost/spirit/phoenix/core/argument.hpp>
+#include <boost/spirit/phoenix/core/reference.hpp>
+#include <boost/spirit/phoenix/core/value.hpp>
+#include <boost/spirit/phoenix/function/function.hpp>
+#include <boost/spirit/phoenix/operator/self.hpp>
+#include <boost/typeof/typeof.hpp>
+#include <functional>
+#include <algorithm>
+#include <vector>
+
+namespace impl
+{
+    struct min_impl
+    {
+        template <typename T1, typename T2>
+        struct result
+        {
+            typedef T1 type;
+        };
+        
+        template <typename T1, typename T2>
+        T1 operator()(T1 t1, T2 t2) const
+        {
+            return (std::min)(t1, t2);
+        }
+    };
+    
+    struct min3_impl
+    {
+        template <typename T1, typename T2, typename T3>
+        struct result
+        {
+            typedef T1 type;
+        };
+        
+        template <typename T1, typename T2, typename T3>
+        T1 operator()(T1 t1, T2 t2, T3 t3) const
+        {
+            return (std::min)((std::min)(t1, t2), t3);
+        }
+    };
+    
+}
+
+using namespace boost;
+using namespace boost::phoenix::iterator_relative;
+using namespace boost::phoenix::arg_names;
+
+const phoenix::static_function< ::impl::min_impl> min = phoenix::static_function< ::impl::min_impl>();
+const phoenix::static_function< ::impl::min3_impl> min3 = phoenix::static_function< ::impl::min3_impl>();
+
+class edit_distance_matrix
+{
+public:
+    edit_distance_matrix(const char *str) : string_b(str)
+    {
+        for (int i=0; i<3; i++)
+            rows[i].resize(string_b.size()+1);
+        distance.resize(string_b.size()+1);
+        for (std::vector<double>::iterator it= rows[0].begin()+1; it!=rows[0].end(); it++)
+            *it = it - rows[0].begin();
+        current_row = prev_row = 0;
+        display();
+        current_row = 1;
+    }
+    void process(char c)
+    {
+        std::string::iterator it_b = string_b.begin();
+        for (distance_type::iterator it=distance.begin()+1; it!=distance.end(); it++, it_b++)
+        {
+            *it = !(*it_b == c);
+            std::cout << "-" << *it;
+        }
+        std::cout << std::endl;
+        rows[current_row].eval(rows[prev_row],distance);
+        display();
+        prev_row = current_row;
+        if (++current_row == 3)
+            current_row = 0;
+    }
+    void display()
+    {
+        for (std::vector<double>::iterator it=rows[current_row].begin();
+             it!=rows[current_row].end(); it++)
+            std::cout << *it << " ";
+        std::cout << std::endl;
+    }
+private:
+    typedef std::vector<double> distance_type;
+    
+    distance_type distance;
+    std::string string_b;
+    phoenix::producer_container<
+        std::vector<double>,
+        BOOST_TYPEOF(min3(prev<1>(arg1) + phoenix::int_<1>(),\
+                         prev<1>(arg2) + prev<0>(arg3),\
+                         prev<0>(arg2) + phoenix::int_<1>())),
+        mpl::vector<
+            BOOST_TYPEOF(prev<0>(arg2) + phoenix::int_<1>())
+        > > rows[3];
+    size_t current_row, prev_row;
+};
+
+int main (int argc, char * const argv[])
+{
+    edit_distance_matrix m("hello");
+    m.process('l');
+    m.process('l');
+    m.process('l');
+    m.process('l');
+        
+    return 0;
+}
+
+//]
Added: sandbox/SOC/2007/signals/libs/dataflow/example/simple_example.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/signals/libs/dataflow/example/simple_example.cpp	2007-08-03 19:29:51 EDT (Fri, 03 Aug 2007)
@@ -0,0 +1,92 @@
+// Copyright 2007 Stjepan Rajko.
+// 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)
+
+//[ simple_example
+
+#include <boost/dataflow/signal/component/storage.hpp>
+#include <boost/dataflow/signal/component/timed_generator.hpp>
+#include <boost/dataflow/signal/connection.hpp>
+
+#include <boost/random/mersenne_twister.hpp>
+#include <boost/random/normal_distribution.hpp>
+#include <boost/random/variate_generator.hpp>
+#include <iostream>
+
+using namespace boost;
+
+// This will be our data processor.  The signature void(double) designates
+// the output signal (we will be sending out an double).  The signals
+// we can receive depend on how we overload operator().
+// For now, we must also specify a result_type (or result) - this requirement
+// will go away.
+class processor : public signals::filter<void (double)>
+{
+public:
+    // Initialize the Gaussian noise generator.
+    processor() : generator(mt, dist) {}
+    
+    typedef void result_type;
+
+    // Receive void(double) signals, add some Gaussian noise, and send
+    // out the modified value.
+    void operator()(double x)
+    {
+        out(x + generator());
+    }
+private:
+    mt19937 mt;
+    normal_distribution<> dist;
+    boost::variate_generator<mt19937&, boost::normal_distribution<> > generator;
+};
+
+// This will be our data output.  We just need to make a function object.
+// For now, we must also give it the appropriate consumer category, and define
+// a result_type (or result) so that Dataflow.Signals knows it is a
+// function object - these requirements will go away.
+class output
+{
+public:
+    typedef dataflow::signal_consumer consumer_category;
+    typedef void result_type;
+    
+    void operator()(double x)
+    {
+        std::cout << x << std::endl;
+    }
+};
+
+int main(int, char* [])
+{
+    // For our data source, we will use timed_generator,
+    // which creates its own thread and outputs it's stored value
+    // at a specified time interval.  We'll store a value of 0 to be sent out.
+    // The signature void(double) specifies that the signal carries a double,
+    // and that there is no return value.
+    signals::timed_generator<void (double), signals::unfused> input(0);
+    
+    // Data processor and output:
+    processor proc;
+    output out;
+    
+    // Now connect the network:
+    input >>= proc >>= out;
+    // If you prefer, you can also do:
+    // connect(input, proc);
+    // connect(proc, out);
+
+    // Tell the source to start producing data, every 0.5s:
+    input.enable(0.5);
+    
+    // take a little nap :-)
+    boost::xtime xt;
+    boost::xtime_get(&xt, boost::TIME_UTC);
+    xt.sec += 10;
+    boost::thread::sleep(xt);
+
+    input.join();
+    return 0;
+}
+
+//]
\ No newline at end of file