thomasmoelhave / tpie

Templated Portable I/O Environment
Other
112 stars 24 forks source link

go() is called on a non-initiator node when there's no initiator in a phase #53

Closed freekvw closed 11 years ago

freekvw commented 11 years ago

I hoped I could code my own initiator outside of the framework and just call begin(), pull() and end() on a pull node, but that was of course not going to work. Instead of telling me there's a phase without an initiator (namely the one containing the output node of a pull-sorter), it apparently tried to call go() on the pull sorter output.

Mortal commented 11 years ago

By definition, an initiator of a phase is a node with no ingoing edges in the actor graph (that is, the node that nobody claims to push to or pull from). It is an error for a phase to have more than one initiator node - in that case, a buffer or other phase boundary is necessary. It is an error for a phase to have no initiators, but in this case you have a cycle in your actor graph, which I don't think we should permit either.

By extension, it is an error to have a passive sorter in a pipeline where nobody pulls the output out of the passive sorter. In this case the output node is treated as a phase initiator which does not make sense.

The current error message in this case is "node subclass [cryptic name] is not an initiator node". Perhaps this should be changed to something along the lines of "go() called on non-initiator - phase has no suitable initiator". What do you think?

I hope you figured out how to write your initiator for your use case.

freekvw commented 11 years ago

I can of course just write a trivial end-node... But shouldn't the graph framework itself instead of the pull sorter output find out that something is wrong?

Mortal commented 11 years ago

In a sense it does due to the default implementation of node::go() which the pull sort output does not override. In almost all cases, a phase will have a node that fits the definition of an initiator node. There is no reflection or flag that indicates that the initiator determined by the definition is the right initiator or not - it finds out by trying to call go() and failing when that has not been overridden.

Is that not also the case for your failing program?

freekvw commented 11 years ago

I don't really get that -- if I would have a proper pull pipeline with an initiator at the end, if the graph doesn't know what is what, how can it determine that it should call go() on the last node?

Mortal commented 11 years ago

It is sort of a special case when you use a passive_sorter and don't use the .output() for anything - in that case, a final pipelining phase is constructed not from a pipe_begin/pipe_end expression, but implicitly from the passive_sorter object on automatic storage (aka on the stack).

I suppose in this case the pull output node from the passive sorter should print a specialized error message (but still throw the same exception).

freekvw commented 11 years ago

It's not a big deal, you can close the bug if you want.