[RFC] event-driven schemes

These patches are an effect of my own need for a data-driven (or
event-driven) scheme in Orocos components, namely for data logging. In
general, I think that this kind of schemes are really well-suited for
any kind of data-processing pipelines.

Any comments are appreciated.

[RFC] event-driven schemes

On Thursday 25 September 2008 19:04:09 Sylvain Joyeux wrote:
> These patches are an effect of my own need for a data-driven (or
> event-driven) scheme in Orocos components, namely for data logging. In
> general, I think that this kind of schemes are really well-suited for
> any kind of data-processing pipelines.
>
> Any comments are appreciated.

Comments:
* I don't see the need for EventDrivenActivity+NewDataEvent combo.
You could have the event signature to be Event< void(PortInterface*) >
which is used in the ports using signal(this) and have the DataDrivenTask
subscribe to it directly. This would remove a lot of book-keeping you have
now.

* I would allow DataDrivenTask to work with 'normal' activities, i.e. always
register/connect the event's of the ports. This moves part of the bookkeeping
in EventDrivenActivity to DataDrivenTask. Next, let trigger() do it's job
(it will/should[1] only fire the activity once, even if called many times in
a row). This will work if you apply the above comment.

* You don't call signal in DataPort::Set and BufferPort::Push

* start() is not real-time because of the ports management. Until now, start()
was always real-time... So it is maybe better to pick up the ports during
configure() / after configureHook().

* The Event API would also allow any user callback to be
registered to each port, in case they don't want to use
updateHook(std::set);

Peter

[1] This is a bit problematic for Mac OS-X, gnulinux,.... We require binary
semaphores to have that behavior of trigger() ( or a perverted use of
mutexes )

[RFC] event-driven schemes

> * I don't see the need for EventDrivenActivity+NewDataEvent combo.
> You could have the event signature to be Event< void(PortInterface*) >
> which is used in the ports using signal(this) and have the DataDrivenTask
> subscribe to it directly. This would remove a lot of book-keeping you have
> now.
Well... EventDrivenActivity is something useful in itself. There can be
other kind of events that port events !

> * I would allow DataDrivenTask to work with 'normal' activities, i.e. always
> register/connect the event's of the ports. This moves part of the bookkeeping
> in EventDrivenActivity to DataDrivenTask. Next, let trigger() do it's job
> (it will/should[1] only fire the activity once, even if called many times in
> a row). This will work if you apply the above comment.
I'm not using trigger() (and use a queue instead) because of the
following problem: if an event is received in-between the exit of the
loop and the exit of the method, then trigger() will not trigger (the
activity is still active) and therefore you have to wait for the next
new event to actually realize that there was one queued.

> * You don't call signal in DataPort::Set and BufferPort::Push
I wrongly assumed that DataPort<> and BufferPort<> were subclassing the
associated Write* and Read* ... I'll fix that.

> * start() is not real-time because of the ports management. Until now, start()
> was always real-time... So it is maybe better to pick up the ports during
> configure() / after configureHook().
A DataDrivenTask will therefore HAVE to have a configure state, but
that's fair enough.

> * The Event API would also allow any user callback to be
> registered to each port, in case they don't want to use
> updateHook(std::set);
They already have it !. The specialized event class can return the
PortInterface itself, so the PortInterface is only a dynamic_cast away
;-)

My problem is that the bookkeeping done in EventDrivenActivity is
actually needed (see the race condition above). So, if we want to have
DataDrivenTask independent of EventDrivenActivity (and use your proposal
for the Event signature), we basically need to copy the same code
twice, which sucks.