Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r48572 - in sandbox/SOC/2007/signals: boost/dataflow/signals/component libs/dataflow/build/xcodeide/dataflow.xcodeproj libs/dataflow/doc libs/dataflow/doc/signals libs/dataflow/example/signals
From: stipe_at_[hidden]
Date: 2008-09-04 03:06:12


Author: srajko
Date: 2008-09-04 03:06:10 EDT (Thu, 04 Sep 2008)
New Revision: 48572
URL: http://svn.boost.org/trac/boost/changeset/48572

Log:
added examples for applicator, instantiator, conditional, modifier
Added:
   sandbox/SOC/2007/signals/libs/dataflow/example/signals/applicator_example.cpp (contents, props changed)
   sandbox/SOC/2007/signals/libs/dataflow/example/signals/conditional_example.cpp (contents, props changed)
   sandbox/SOC/2007/signals/libs/dataflow/example/signals/instantiator_example.cpp (contents, props changed)
   sandbox/SOC/2007/signals/libs/dataflow/example/signals/modifier_example.cpp (contents, props changed)
Text files modified:
   sandbox/SOC/2007/signals/boost/dataflow/signals/component/timed_generator.hpp | 29 ++++++++++++++++--
   sandbox/SOC/2007/signals/libs/dataflow/build/xcodeide/dataflow.xcodeproj/project.pbxproj | 8 +++++
   sandbox/SOC/2007/signals/libs/dataflow/doc/dataflow.qbk | 4 ++
   sandbox/SOC/2007/signals/libs/dataflow/doc/signals/components.qbk | 60 ++++++++++++++++++++++++++++++++++++++++
   sandbox/SOC/2007/signals/libs/dataflow/example/signals/Jamfile.v2 | 6 +++
   5 files changed, 102 insertions(+), 5 deletions(-)

Modified: sandbox/SOC/2007/signals/boost/dataflow/signals/component/timed_generator.hpp
==============================================================================
--- sandbox/SOC/2007/signals/boost/dataflow/signals/component/timed_generator.hpp (original)
+++ sandbox/SOC/2007/signals/boost/dataflow/signals/component/timed_generator.hpp 2008-09-04 03:06:10 EDT (Thu, 04 Sep 2008)
@@ -22,13 +22,13 @@
     typedef storage<Signature, OutSignal, SignalArgs> base_type;
 public:
         /// Default constructor. Starts the thread, but signals won't be sent until the enable() function is called.
- timed_generator() : terminating(false), enabled(false)
+ timed_generator() : terminating(false), enabled(false), m_completed(false)
         {
                 thread_object = new boost::thread(boost::bind(&timed_generator::thread_function, boost::ref(*this)));
         }
     /// Forwarding constructor for underlying storage
     template<typename T>
- timed_generator(const T &t) : base_type(t), terminating(false), enabled(false)
+ timed_generator(const T &t) : base_type(t), terminating(false), enabled(false), m_completed(false)
     {
                 thread_object = new boost::thread(boost::bind(&timed_generator::thread_function, boost::ref(*this)));
     }
@@ -46,6 +46,7 @@
                 boost::xtime_get(&xt, boost::TIME_UTC);
                 count = signal_count;
                 enabled = true;
+ m_completed = false;
                 cond.notify_all();
         };
         /// Stops the sending of signals and suspends the thread.
@@ -69,6 +70,18 @@
                 cond.notify_all();
                 delete thread_object;
         }
+ void wait_until_completed()
+ {
+ boost::mutex::scoped_lock lock(m_completion_mutex);
+ while(!m_completed)
+ m_completion_condition.wait(m_completion_mutex);
+ }
+ boost::mutex &completion_mutex()
+ { return m_completion_mutex; }
+ boost::condition &completion_condition()
+ { return m_completion_condition; }
+ bool completed()
+ { return m_completed; }
 private:
         void thread_function()
         {
@@ -76,7 +89,7 @@
                 {
                         {
                                 boost::mutex::scoped_lock lock(mutex_);
- if (!enabled)
+ while(!enabled && !terminating)
                                         cond.wait(lock);
                         }
                         if (terminating) break;
@@ -95,20 +108,28 @@
                         base_type::send();
                         if (count)
                                 if (--count==0)
+ {
                                         disable();
+ boost::mutex::scoped_lock lock(m_completion_mutex);
+ m_completed = true;
+ m_completion_condition.notify_all();
+ }
                 }
                 cond.notify_all();
         }
         /// Class mutex.
         boost::mutex mutex_;
         boost::condition cond;
- boost::xtime xinterval;
+ boost::xtime xinterval;
         volatile bool terminating;
         boost::xtime xt;
         int count;
 
         boost::thread *thread_object;
         volatile bool enabled;
+ bool m_completed;
+ boost::mutex m_completion_mutex;
+ boost::condition m_completion_condition;
 };
 
 } } // namespace boost::signals

Modified: sandbox/SOC/2007/signals/libs/dataflow/build/xcodeide/dataflow.xcodeproj/project.pbxproj
==============================================================================
--- sandbox/SOC/2007/signals/libs/dataflow/build/xcodeide/dataflow.xcodeproj/project.pbxproj (original)
+++ sandbox/SOC/2007/signals/libs/dataflow/build/xcodeide/dataflow.xcodeproj/project.pbxproj 2008-09-04 03:06:10 EDT (Thu, 04 Sep 2008)
@@ -257,6 +257,10 @@
                 08E228FE0E62084100D1C2AF /* Jamfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.jam; path = Jamfile; sourceTree = "<group>"; };
                 08E229020E6208AC00D1C2AF /* threadpool_example.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = threadpool_example.cpp; sourceTree = "<group>"; };
                 08EBA7590CFF8B6D0080E225 /* example.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = example.cpp; sourceTree = "<group>"; };
+ 08ED261F0E6F23C4007B95D9 /* conditional_example.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = conditional_example.cpp; sourceTree = "<group>"; };
+ 08ED26400E6F2946007B95D9 /* applicator_example.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = applicator_example.cpp; sourceTree = "<group>"; };
+ 08ED264D0E6F2A5E007B95D9 /* instantiator_example.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = instantiator_example.cpp; sourceTree = "<group>"; };
+ 08ED264E0E6F2A74007B95D9 /* modifier_example.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = modifier_example.cpp; sourceTree = "<group>"; };
                 08EF045E0CEBF1AD002ABBBC /* port_t.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = port_t.hpp; sourceTree = "<group>"; };
                 08EF9B220C5D506A00D4D206 /* applicator.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = applicator.hpp; sourceTree = "<group>"; };
                 08EF9B230C5D506A00D4D206 /* chain.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = chain.hpp; sourceTree = "<group>"; };
@@ -1149,6 +1153,10 @@
                                 08A0E54C0D7A7674009B11DD /* quick_start_examples.cpp */,
                                 083F151E0D8A356500D0F8B7 /* tracking_consumer_example.cpp */,
                                 08998BA10D8B2094006ED577 /* specific_tracking_consumer_example.cpp */,
+ 08ED261F0E6F23C4007B95D9 /* conditional_example.cpp */,
+ 08ED26400E6F2946007B95D9 /* applicator_example.cpp */,
+ 08ED264D0E6F2A5E007B95D9 /* instantiator_example.cpp */,
+ 08ED264E0E6F2A74007B95D9 /* modifier_example.cpp */,
                         );
                         path = signals;
                         sourceTree = "<group>";

Modified: sandbox/SOC/2007/signals/libs/dataflow/doc/dataflow.qbk
==============================================================================
--- sandbox/SOC/2007/signals/libs/dataflow/doc/dataflow.qbk (original)
+++ sandbox/SOC/2007/signals/libs/dataflow/doc/dataflow.qbk 2008-09-04 03:06:10 EDT (Thu, 04 Sep 2008)
@@ -188,6 +188,10 @@
 [import ../example/signals/intro_example.cpp]
 [import ../example/signals/gil_example.cpp]
 [import ../example/signals/quick_start_examples.cpp]
+[import ../example/signals/applicator_example.cpp]
+[import ../example/signals/conditional_example.cpp]
+[import ../example/signals/instantiator_example.cpp]
+[import ../example/signals/modifier_example.cpp]
 
 [import ../../../boost/dataflow/vtk/support.hpp]
 [import ../example/VTK/Cone.cxx]

Modified: sandbox/SOC/2007/signals/libs/dataflow/doc/signals/components.qbk
==============================================================================
--- sandbox/SOC/2007/signals/libs/dataflow/doc/signals/components.qbk (original)
+++ sandbox/SOC/2007/signals/libs/dataflow/doc/signals/components.qbk 2008-09-04 03:06:10 EDT (Thu, 04 Sep 2008)
@@ -71,6 +71,14 @@
 
 * [counter]
 
+[heading Example]
+
+Here is an example of a logging counter - a counter which can be used with
+any signal signature, and will record the number of passing signals as well
+as display a message each time:
+
+[applicator_example]
+
 [endsect][/applicator]
 
 [section:conditional conditional]
@@ -89,6 +97,12 @@
 
 * [junction]
 
+[heading Example]
+
+Here is a simple implementation of a gate which can be used with any signature:
+
+[conditional_example]
+
 [endsect][/conditional]
 
 [section:instantiator instantiator]
@@ -107,6 +121,43 @@
 
 * [mutex]
 
+[heading Example]
+
+The following example shows how a mutex component can be built (it is just
+an instantiator that instantiates a scoped_lock over a mutex whenever
+a signal passes).
+
+[instantiator_example]
+
+A sample run of this example produces:
+
+[pre
+
+With mutex:
+#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9
+#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9
+#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9
+#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9
+#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9
+#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9
+#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9
+#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9
+#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9
+#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9
+Without mutex:
+#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8##09##10##21##32##43##54##65##76##87##98##09#
+1#2#3#4#5#6#7#8#9#0#1##20##31##42##53##64##75##86##97
+#8##09##10##21##32##43##54##65##76##87##98##09##10##21##32##43##54##65##76##87##98##09#
+1##20##31##42##53##64##75##86##97
+#8##9#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9
+0##10#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9
+#1#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9
+#2#3#4#5#6#7#8##09##10##21##32##43##54##65##76##87##98##09##10##21##32##43##54##65##76##87##98##09#
+1##20##31##42##53##64##75##86##97
+#8#9#0#1#2#3#4#5#6#7#8#9#0#1#2#3#4#5#6#7#8#9
+
+]
+
 [endsect][/instantiator]
 
 [section:modifier modifier]
@@ -125,6 +176,15 @@
 
 * [function]
 
+[heading Example]
+
+The following example shows how to implement a generic multiplier component.
+This one can be used with any signature with non-reference arguments (it isn't
+hard to make it allow reference arguments, but it would take away from the
+clarity of the example).
+
+[modifier_example]
+
 [endsect][/modifier]
 
 [endsect][/generic]

Modified: sandbox/SOC/2007/signals/libs/dataflow/example/signals/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/signals/libs/dataflow/example/signals/Jamfile.v2 (original)
+++ sandbox/SOC/2007/signals/libs/dataflow/example/signals/Jamfile.v2 2008-09-04 03:06:10 EDT (Thu, 04 Sep 2008)
@@ -22,4 +22,8 @@
 exe gil_example : gil_example.cpp /boost/thread//boost_thread/<link>static ;
 exe quick_start_examples : quick_start_examples.cpp ;
 exe tracking_consumer_example : tracking_consumer_example.cpp ;
-exe specific_tracking_consumer_example : specific_tracking_consumer_example.cpp ;
\ No newline at end of file
+exe specific_tracking_consumer_example : specific_tracking_consumer_example.cpp ;
+exe applicator_example : applicator_example.cpp ;
+exe conditional_example : conditional_example.cpp ;
+exe instantiator_example : instantiator_example.cpp /boost/thread//boost_thread/<link>static ;
+exe modifier_example : modifier_example.cpp ;

Added: sandbox/SOC/2007/signals/libs/dataflow/example/signals/applicator_example.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/signals/libs/dataflow/example/signals/applicator_example.cpp 2008-09-04 03:06:10 EDT (Thu, 04 Sep 2008)
@@ -0,0 +1,74 @@
+// Copyright Stjepan Rajko 2007. Use, modification and
+// distribution is subject to 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)
+
+//[ applicator_example
+
+#include <boost/dataflow/signals/component/applicator.hpp>
+#include <boost/dataflow/signals/component/storage.hpp>
+#include <boost/dataflow/signals/connection.hpp>
+
+#include <iostream>
+
+using namespace boost;
+
+// A function that will be executed each time a signal passes.
+template<typename T>
+struct postincrement_and_log
+{
+ void operator()(T &t)
+ {
+ t++;
+ std::cout << "Signal number " << t << " has passed." << std::endl;
+ }
+};
+
+// We will now implement a logging counter component that can be used with
+// any signal signature. It will increment a counter and display a message
+// with each passing signal.
+template<typename Signature>
+class logging_counter : public boost::signals::applicator<
+ // the first parameter is the derived class
+ logging_counter<Signature>,
+ // the second parameter determines the type of conditional::member,
+ // which we will use to store the number of signals passed.
+ unsigned,
+ // the third parameted specifies a function which will be applied to the
+ // member with each passing signal.
+ postincrement_and_log<unsigned>,
+ // the fourth parameter determines the signal Signature the component
+ // consumes and produces.
+ Signature>
+{
+public:
+ // Initializes the internal counter to 0.
+ logging_counter()
+ { reset(); }
+
+ // Sets the internal counter to 0.
+ void reset()
+ { logging_counter::member = 0; }
+
+ // Return the internal signal counter.
+ unsigned count() const
+ { return logging_counter::member; }
+};
+
+int main()
+{
+ signals::storage<void ()> producer;
+ logging_counter<void ()> counter;
+
+ producer >>= counter;
+
+ BOOST_ASSERT(counter.count() == 0);
+
+ producer.send();
+ producer.send();
+ BOOST_ASSERT(counter.count() == 2);
+
+ return 0;
+}
+
+//]
\ No newline at end of file

Added: sandbox/SOC/2007/signals/libs/dataflow/example/signals/conditional_example.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/signals/libs/dataflow/example/signals/conditional_example.cpp 2008-09-04 03:06:10 EDT (Thu, 04 Sep 2008)
@@ -0,0 +1,84 @@
+// Copyright Stjepan Rajko 2007. Use, modification and
+// distribution is subject to 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)
+
+//[ conditional_example
+
+#include <boost/dataflow/signals/component/conditional.hpp>
+#include <boost/dataflow/signals/component/counter.hpp>
+#include <boost/dataflow/signals/component/storage.hpp>
+#include <boost/dataflow/signals/connection.hpp>
+
+using namespace boost;
+
+// just an identity function
+template<typename T>
+struct identity
+{
+ T operator ()(T t) const
+ {
+ return t;
+ }
+};
+
+// We will implement a generic gate, which be used with any signal signature.
+// To do so, we inherit from the conditional class.
+template<typename Signature>
+class my_gate
+ : public boost::signals::conditional<
+ // the first parameter is the derived class
+ my_gate<Signature>,
+ // the second parameter determines the type of conditional::member,
+ // which we will use to store whether the gate is open or closed.
+ bool,
+ // the third parameted specifies a function which will be used on the
+ // member to determine whether conditional should forward the signal
+ // or not. In our case, it is just identity.
+ identity<bool>,
+ // the fourth parameter determines the signal Signature the component
+ // consumes and produces.
+ Signature>
+{
+public:
+ // Initialize the gate to be opened.
+ my_gate(bool opened=true)
+ {
+ my_gate::member=opened;
+ }
+ // Opens the gate (signals will be forwarded).
+ void open()
+ {
+ my_gate::member = true;
+ }
+ // Closes the gate (signals will not be forwarded).
+ void close()
+ {
+ my_gate::member = false;
+ }
+};
+
+int main()
+{
+ signals::storage<void ()> producer;
+ signals::counter<void ()> consumer;
+ my_gate<void ()> gate;
+
+ producer >>= gate >>= consumer;
+
+ producer.send();
+ BOOST_ASSERT(consumer.count() == 1);
+
+ gate.close();
+
+ producer.send();
+ BOOST_ASSERT(consumer.count() == 1);
+
+ gate.open();
+
+ producer.send();
+ BOOST_ASSERT(consumer.count() == 2);
+ return 0;
+}
+
+//]
\ No newline at end of file

Added: sandbox/SOC/2007/signals/libs/dataflow/example/signals/instantiator_example.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/signals/libs/dataflow/example/signals/instantiator_example.cpp 2008-09-04 03:06:10 EDT (Thu, 04 Sep 2008)
@@ -0,0 +1,100 @@
+// Copyright Stjepan Rajko 2007. Use, modification and
+// distribution is subject to 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)
+
+//[ instantiator_example
+
+#include <boost/dataflow/signals/component/filter.hpp>
+#include <boost/dataflow/signals/component/instantiator.hpp>
+#include <boost/dataflow/signals/component/timed_generator.hpp>
+#include <boost/dataflow/signals/connection.hpp>
+#include <boost/thread/mutex.hpp>
+
+#include <string>
+
+using namespace boost;
+
+// Ensures a component is processing only one signal at a time when using multiple threads.
+// To do so, we need to instantiate a scoped lock over a mutex each time we
+// are handling a signal. We can inherit from instantiator to accomplish this.
+template<typename Signature>
+class my_mutex : public
+ boost::signals::instantiator<
+ // the first parameter is the derived class
+ my_mutex<Signature>,
+ // the second parameter determines the type of conditional::member,
+ // which we will be our mutex.
+ boost::mutex,
+ // the third parameter determines the object which will be instantiated
+ // with the member as the constructor argument.
+ // In our case, that is the scoped_lock.
+ boost::mutex::scoped_lock,
+ // the fourth parameter determines the signal Signature the component
+ // consumes and produces.
+ Signature>
+{
+ // that's it.
+};
+
+// a consumer component, to occupy some time.
+class printer : public boost::signals::consumer<printer>
+{
+public:
+ void operator()(const std::string &message)
+ {
+ for (int j=0; j<3; j++)
+ for (int i=0; i<10; i++)
+ std::cout << message << i;
+ std::cout << std::endl;
+ }
+};
+
+int main()
+{
+ // timed_generators send signals in their own thread
+ signals::timed_generator<void ()> timer1;
+ signals::timed_generator<void ()> timer2;
+
+ // other components
+ my_mutex<void ()> lock;
+ signals::storage<void (const std::string &)> producer("#");
+ printer consumer;
+
+ // first, with the mutex:
+ std::cout << "With mutex:" << std::endl;
+ producer >>= consumer;
+ timer1 >>= lock >>= producer.send_slot();
+ timer2 >>= lock;
+
+ // set each timer to send a signal 5 times, in 0s intervals (i.e., instantly)
+ timer1.enable(0.0, 5);
+ timer2.enable(0.0, 5);
+
+ // wait until they are done.
+ timer1.wait_until_completed();
+ timer2.wait_until_completed();
+
+
+ // now, without the mutex (reconnect timer1 and timer2 directly to producer)
+ std::cout << "Without mutex:" << std::endl;
+ disconnect_all(timer1);
+ disconnect_all(timer2);
+
+ timer1 >>= producer.send_slot();
+ timer2 >>= producer.send_slot();
+
+ // set each timer to send a signal 5 times, in 0s intervals (i.e., instantly)
+ timer1.enable(0.0, 5);
+ timer2.enable(0.0, 5);
+
+ // wait until they are done.
+ timer1.wait_until_completed();
+ timer2.wait_until_completed();
+
+ timer1.join();
+ timer2.join();
+ return 0;
+}
+
+//]
\ No newline at end of file

Added: sandbox/SOC/2007/signals/libs/dataflow/example/signals/modifier_example.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/signals/libs/dataflow/example/signals/modifier_example.cpp 2008-09-04 03:06:10 EDT (Thu, 04 Sep 2008)
@@ -0,0 +1,114 @@
+// Copyright Stjepan Rajko 2007. Use, modification and
+// distribution is subject to 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)
+
+//[ modifier_example
+
+#include <boost/dataflow/signals/component/modifier.hpp>
+#include <boost/dataflow/signals/component/storage.hpp>
+#include <boost/dataflow/signals/connection.hpp>
+
+#include <boost/bind.hpp>
+#include <boost/fusion/include/transform.hpp>
+
+using namespace boost;
+
+// A somewhat generic multiplier (it will multiply any type with a double).
+// We will use this as a transform.
+struct multiply
+{
+ template<typename FArgs>
+ struct result;
+
+ template<typename F, typename T>
+ struct result<F(const T &)>
+ {
+ typedef T type;
+ };
+
+ multiply(double factor)
+ : m_factor(factor)
+ {}
+
+ template<typename T>
+ T operator()(T t) const
+ {
+ return t * m_factor;
+ }
+
+ double m_factor;
+};
+
+// The implementation of the multiplier component functionality.
+template<typename Signature>
+struct multiplier_impl
+{
+ multiplier_impl(double factor)
+ : m_factor(factor)
+ {}
+
+ // This is where the work happens.
+ // seq will be a fusion sequence with all of the arguments, and we will
+ // return the transformed values (using multiply as the transform).
+ template<typename Seq>
+ Seq operator()(const Seq &seq)
+ {
+ return boost::fusion::transform(seq, multiply(m_factor));
+ }
+protected:
+ double m_factor;
+};
+
+// The actual component will inherit from modifier.
+template<typename Signature>
+class multiplier
+ : public boost::signals::modifier<
+ // the first parameter is the derived class.
+ multiplier<Signature>,
+ // the second parameter is the implementation class.
+ multiplier_impl<Signature>,
+ // the fourth parameter determines the signal Signature the component
+ // consumes and produces.
+ Signature>
+{
+public:
+ typedef boost::signals::modifier<multiplier<Signature>, multiplier_impl<Signature>, Signature>
+ base_type;
+
+ // the constructor parameter will be forwarded to the implementation class
+ multiplier(double multiplier)
+ : base_type(multiplier)
+ {}
+};
+
+int main()
+{
+ {
+ signals::storage<void (int, double)> result;
+ multiplier<void (int, double)> multiply_by_3 (3);
+
+ // result will store the result of the multiplication
+ multiply_by_3 >>= result;
+ multiply_by_3(1, 1.5);
+
+ BOOST_ASSERT(result.at<0>() == 3);
+ BOOST_ASSERT(result.at<1>() == 4.5);
+ }
+ {
+ signals::storage<void (float, int, double)> result;
+ multiplier<void (float, int, double)> multiply_by_half (0.5);
+
+ // result will store the result of the multiplication
+ multiply_by_half >>= result;
+ multiply_by_half(1.0f, 9, 9.0);
+
+ BOOST_ASSERT(result.at<0>() == 0.5f);
+ BOOST_ASSERT(result.at<1>() == 4);
+ BOOST_ASSERT(result.at<2>() == 4.5);
+ }
+
+ 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