
I've recently been working on a system making use of complex pipelines of loaders and events, and was looking at some similar "signal flow" concepts. A few comments: 1) This "signal flow" library sounds very similar to the "pipes and filters" pattern. If the name invokes that relationship, it might get more use (if it is up to the semantics of pipes and filters). 2) Using functions or functors directly would avoid the need for any signal_link glue in many cases. The output signal type could be derived from the return type of the function. /** Function which upon receiving an image signal, outputs the horizontally flipped image **/ Image flipImage(Image inputImage); /** Functor which performs some analysis **/ struct AnalyzeImage { Vector operator()(Image inputImage); }; ...later... boost::function<Image (Image)> flipper = flipImage; boost::function<Vector (Image)> analysis = AnalyzeImage(); // perform the whole video analysis and display the results frame_rate >>= video_generator >>= differencer >>= flipper >>= analysis >>= database >>= display1; I added the intermediate function object, because I know you can get the result type and signature from it...perhaps you can be clever and avoid it in most cases. Or at least provide an in-line glue syntax like: signal_func<Image (Image)>(f) This has the benefit that I need no signal_link glue objects, nor does my functional code require any knowledge of signals, slots, or signal_links. 3) Rationale? Your example usage seems to be almost equivalent to: void imagePipeline() { Image img = video_generator(); img = differencer(img); img = flipper(img); Vector vec = analysis(img); database(vec); display1(img); } Obviously this code is more readable by any C++ programmer and has no boost dependencies, and could even be called by a signal. So exactly what is the rationale for signal_flow? The rationale could be the ability to dynamically reconfigure pipelines at runtime. But your example doesn't seem to provide a way to do this (no "flow traversal" or visitor iteration). The rationale could be to dynamically build pipelines at runtime. But your syntax is primarily for multiple stages at compile-time, and if you start building your pipeline one at a time you can just use signal.connect() calls. The rationale could be to provide parallelism to a data flow. But boost::signals doesn't have (yet) the functionality to provide this. There is something here, but it is hard to put my finger on it... Braddock Gaskill Dockside Vision Inc

These operator overloads for connecting multiple signals seem too cutesy and confusing. How often do these long chains of signals get connected together? I would imagine at most a dozen such chains for a complex application but maybe I'm wrong. Braddock brings up good points and I find his imagePipeline function much easier to read (it will also almost certainly be easier to debug and to mentally assure myself of correctness). - Michael Marcin
participants (2)
-
Braddock Gaskill
-
Michael Marcin