Boost logo

Boost-Commit :

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 &it;
+ };
+
+ 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 &it;
+ 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 &it;
+ 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


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk