3 | | I will add some of the information here soon. |
| 3 | The Signal Network library aims to facilitate the |
| 4 | implementation and interconnection of objects into signal networks using Boost.Signals. |
| 5 | To understand the concept of signals (data generators / senders) and slots (data consumers / receivers), |
| 6 | please see the Boost.Signals [http://www.boost.org/doc/html/signals.html documentation] |
| 7 | and the associated [http://www.boost.org/doc/html/signals/tutorial.html tutorial]. |
| 8 | |
| 9 | This is a proposal for development of the Signal Network library as a part of |
| 10 | Google Summer of Code and evential inclusion into Boost. Depending on what is preferred, |
| 11 | the Signal Network library can be included into Boost.Signals or considered as a separate library. |
| 12 | |
| 13 | If you're interested, you may want to examine the [http://dancinghacker.com/code/signet/ documentation for the prototype implementation]. |
| 14 | |
| 15 | The Signal Network library is to provide |
| 16 | * a concise operator based syntax that facilitates construction and readiblity of signal networks |
| 17 | * mechanisms that facilitate construction of signal network components |
| 18 | * implemented building-block components that are applicable to a wide range of signal networks |
| 19 | * detailed documentation (tutorial, examples and reference) of all of the above |
| 20 | |
| 21 | The development platforms are |
| 22 | * OS X / Xcode with Apple's branch of GCC |
| 23 | * Windows / MSVC8.0 |
| 24 | |
| 25 | == Motivation == |
| 26 | |
| 27 | Boost.Signals provides an excellent mechanism which can be used to dynamically configure the flow of data within |
| 28 | a program. This is helpful for registering callbacks, for event passing, and for signal processing applications. |
| 29 | |
| 30 | However, when dealing with more complicated networks, there are several improvements to Boost.Signals |
| 31 | that could facilitate the construction, configuration, and execution of said networks. Several categories which could use |
| 32 | some improvement are listed below. |
| 33 | |
| 34 | For simplicity, the examples in this documentation deal with signals which carry numbers, |
| 35 | and components which manipulate them. The same principles are applicable to many kinds of signal oriented |
| 36 | applications (e.g., ones where the signals carry event information, video frames, audio buffers, etc.). |
| 37 | |
| 38 | === Conciseness and readability of code === |
| 39 | In complex signal-based applications, many components are signal ''filters'' or some kind (i.e., they |
| 40 | receive some input, process it, and send some output). For processing of any substantial complexity, |
| 41 | each type of filter is most likely implemented as a class, with one or more member boost::signal |
| 42 | objects serving as signal outputs, and one or more member functions serving as input slots. |
| 43 | |
| 44 | Suppose we would like to connect a network consisting of a signal generator, a couple of filters, |
| 45 | and a couple of signal consumers (say, display components). The components might be declared as follows: |
| 46 | |
| 47 | {{{ |
| 48 | #!cpp |
| 49 | signal_generator generator; // contains a boost::signal accessible via signal_generator::default_signal() |
| 50 | signal_filter1 filter1; // contains a boost::signal accessible via signal_filter1::default_signal(), |
| 51 | // and a slot function operator() |
| 52 | signal_filter2 filter2; // contains a boost::signal accessible via signal_filter2::default_signal(), |
| 53 | // and a slot function operator() |
| 54 | signal_display display1, display2; // contains a slot function operator() |
| 55 | }}} |
| 56 | |
| 57 | To connect the network, the following would be necessary using Boost.Signals: |
| 58 | |
| 59 | ==== Boost.Signals syntax: ==== |
| 60 | |
| 61 | {{{ |
| 62 | // connect the generator to filter1 |
| 63 | generator.default_signal().connect(boost::bind(&signal_filter1::operator(), boost::ref(filter1))); |
| 64 | // connect filter1 to filter2 |
| 65 | filter1.default_signal().connect(boost::bind(&signal_filter2::operator(), boost::ref(filter2))); |
| 66 | // connect the output of each filter to a display |
| 67 | filter1.default_signal().connect(boost::bind(&signal_display::operator(), boost::ref(display1))); |
| 68 | filter2.default_signal().connect(boost::bind(&signal_display::operator(), boost::ref(display2))); |
| 69 | }}} |
| 70 | |
| 71 | The code above is rather long to write, and might not be particularly readable. What we would like to |
| 72 | do instead is something more concise and readable: |
| 73 | ==== Proposed/desired syntax: ==== |
| 74 | |
| 75 | {{{ |
| 76 | // connect (>>=) generator to filter1, |
| 77 | // branch (|) from filter1 to both display1 and filter2, |
| 78 | // and connect (>>=) filter2 to display2. |
| 79 | generator |
| 80 | >>= filter1 |
| 81 | | display1 |
| 82 | | filter2 >>= display2; |
| 83 | }}} |
| 84 | |
| 85 | The above code is much more concise, and after getting familiar with the syntax, understanding the structure of |
| 86 | the signal network is easy and quick. |
| 87 | |
| 88 | === Flow control components === |
| 89 | In many cases, we would like to modify the flow of signals after the network |
| 90 | has been constructed. Boost.Signals allows us to change the network by disconnecting old or |
| 91 | creating new connections. So, for example, if we wanted to introduce a second |
| 92 | signal generator into the system (e.g., generator2), we could use signal::disconnect (or |
| 93 | signal::disconnect_all_slots) |
| 94 | and signal::connect to toggle between the two sources: |
| 95 | |
| 96 | ==== Boost.Signals flow control: ==== |
| 97 | |
| 98 | {{{ |
| 99 | // switch to the other signal generator: |
| 100 | generator.default_signal().disconnect_all_slots(); |
| 101 | generator2.default_signal().connect(boost::bind(&signal_filter1::operator(), boost::ref(filter1))); |
| 102 | }}} |
| 103 | |
| 104 | There are a few potential problems with this approach. First, the syntax is again perhaps a little too involved. |
| 105 | And second, altering the |
| 106 | network while signals are being sent may require extra care (especially in multi-threaded |
| 107 | settings). Hence, depending on the situation, it might be difficult to use |
| 108 | this approach |
| 109 | to alternate between the two sources (perhaps a custom object would need to be written |
| 110 | to choose the appropriate source). |
| 111 | |
| 112 | Instead, it would be desirable to have ready-made components which can be used to alter |
| 113 | the flow of signals without changing the architecture of the network: |
| 114 | |
| 115 | ==== Proposed/desired flow control: ==== |
| 116 | |
| 117 | {{{ |
| 118 | // introduce a selector into the network |
| 119 | signal_selector selector; |
| 120 | |
| 121 | // the generators are now connected to the selector |
| 122 | generator >>= selector.slot1; |
| 123 | generator2 >>= selector.slot2; |
| 124 | |
| 125 | // and the rest of the network is now constructed as follows: |
| 126 | selector |
| 127 | >>= filter1 |
| 128 | | display1 |
| 129 | | filter2 >>= display2; |
| 130 | |
| 131 | |
| 132 | // Now we could choose the source as follows: |
| 133 | selector.select(1); // select input coming into slot1 |
| 134 | ... |
| 135 | selector.select(2); // select input coming into slot2 |
| 136 | ... |
| 137 | selector.select(0); // select no input |
| 138 | }}} |
| 139 | |
| 140 | The latter approach offers more robust control, and can be implemented in a thread-safe way |
| 141 | (safe even when the generated signals are in threads separate from the reconfiguring thread). |
| 142 | Similar arguments can be made for other flow control components such as junctions and gates. |
| 143 | |
| 144 | === Other building-block signal network components === |
| 145 | There are many other components that are usable in various signal network settings. |
| 146 | The Signal Network library would provide a set of such commonly needed components, |
| 147 | such as templates for signal generators, collectors, threading components, etc. |