Boost logo

Boost :

Subject: Re: [boost] [review] Dataflow Review starts today, September 1st
From: Stjepan Rajko (stipe_at_[hidden])
Date: 2008-09-04 13:59:20

On Thu, Sep 4, 2008 at 1:06 AM, Kowalke Oliver (QD IT PA SI)
<Oliver.Kowalke_at_[hidden]> wrote:
> Hello,
> I took a quick look into the lib and I've following questions:
> - How does Boost.DataFlow support exchanging data in both directions between two components (duplex communication)?
> Example: stack of network-protocols:
> service_contract >>= serializer >>= encoder >>= protocol_1 >>= protocol_2 >>= transport (send data)
> transport >>= protocol_2 >>= protocol_1 >>= encoder >>= deserializer >>= service_contract (receive data)

Depends on the exact details. If the communication is always such
that the left component initiates the exchange by sending its piece of
data, and then the right component responds, in the Dataflow.Signals
layer you could use a signature like `type1(type2), i.e. use the
argument to send the data to the right and the return value to send
the data to the left.

Here is an example (untested)

class duplex_multiplier : public signals::filter<duplex_multiplier, int(int)>
    int operator()(int x)
        // double the value received from the left, and send that to the right
        int response_from_right = out(x*2);
        // then return triple the response to the component on the left
        return 3 * response_from_right;

// signal consumers don't need to know their signature
class loop_back : public signals::consumer<loop_back>
    int operator()(int x);
        // just return the received value back to the left
        return x;

// now:
duplex_multiplier a,b,c;
loop_back d;

// the following connections are bidirectional because of the int(int) signature
// so >>= is misleading and a different operator might be better to use

a >>= b >>= c >>= d;

int response = a(1); // should return 1*2*2*2*3*3*3

If in your scenario a component would need to respond instantly
(before sending data to the right and receiving a response), then it
would need to send the rightward signal in a separate thread.

If, on the other hand, you have a true duplex scenario where both the
leftmost and rightmost component can initiate a signal, then each
component would need an additional signal. The network would then
look something like:

c1 >>= c2 >>= c3 >>= c4
c4.left_signal() >>= c3.left_signal() >>= c2.left_signal() >>= c1

This is similar to:

> - If one consumer is connected to multiple producers, how can the consumer selectively disconnect from specific producers?

I would recommend storing the connection object and using it to break
the connection, as shown here:

At one point, I put together an example of how this tracking of
connection objects by the consumer could be done automatically:

In these examples, the consumer was programmed to disconnect itself
from any producer that sends it a signal after it has already received
a specified number of signals, but the logic could be changed.

> Contrary to some other posts -I find the syntax of ovelroaded operators not confusing:
>>>= push sematic
> =<< pull semantic
> The pipe operator '|' could also be used in the parallel execution semantic.

I am also happy with >>= (and adding <<= to indicate pull semantics),
but the example above showed another problem - if the connection is
bidirectional, neither >>= or <<= seem appropriate.

What do people think of making the operator choice completely up to
the user (i.e., the user can specify what operator they would like to
use for what operation, with some default mappings provided)?

Thanks for taking a look at the library!



Boost list run by bdawes at, gregod at, cpdaniel at, john at