@@ -105,6 +105,10 @@ class ContainerBasePrivate : public StagePrivate
105105
106106 void validateConnectivity () const override ;
107107
108+ // Containers derive their required interface from their children
109+ // UNKNOWN until resolveInterface was called
110+ InterfaceFlags requiredInterface () const override { return required_interface_; }
111+
108112 // forward these methods to the public interface for containers
109113 bool canCompute () const override ;
110114 void compute () override ;
@@ -115,21 +119,17 @@ class ContainerBasePrivate : public StagePrivate
115119protected:
116120 ContainerBasePrivate (ContainerBase* me, const std::string& name);
117121
118- // Set child's push interfaces: allow pushing if child requires it or
119- // if the interface is unknown: in this case greedily assume a push interface.
120- // If, during pruneInterface() later, we notice that it's not needed, prune there.
121- inline void setChildsPushBackwardInterface (Stage& child) {
122- InterfaceFlags required = child.pimpl ()->requiredInterface ();
123- bool allowed = (required & WRITES_PREV_END) || (required == UNKNOWN);
124- child.pimpl ()->setPrevEnds (allowed ? pending_backward_ : InterfacePtr ());
122+ // Set child's push interfaces: allow pushing if child requires it.
123+ inline void setChildsPushBackwardInterface (StagePrivate* child) {
124+ InterfaceFlags required = child->requiredInterface ();
125+ bool allowed = (required & WRITES_PREV_END);
126+ child->setPrevEnds (allowed ? pending_backward_ : InterfacePtr ());
125127 }
126- inline void setChildsPushForwardInterface (Stage& child) {
127- InterfaceFlags required = child. pimpl () ->requiredInterface ();
128- bool allowed = (required & WRITES_NEXT_START) || (required == UNKNOWN) ;
129- child. pimpl () ->setNextStarts (allowed ? pending_forward_ : InterfacePtr ());
128+ inline void setChildsPushForwardInterface (StagePrivate* child) {
129+ InterfaceFlags required = child->requiredInterface ();
130+ bool allowed = (required & WRITES_NEXT_START);
131+ child->setNextStarts (allowed ? pending_forward_ : InterfacePtr ());
130132 }
131- // report error about mismatching interface (start or end as determined by mask)
132- void mismatchingInterface (InitStageException& errors, const StagePrivate& child, const InterfaceFlags mask) const ;
133133
134134 // / copy external_state to a child's interface and remember the link in internal_to map
135135 void copyState (Interface::iterator external, const InterfacePtr& target, bool updated);
@@ -139,6 +139,9 @@ class ContainerBasePrivate : public StagePrivate
139139 auto & internalToExternalMap () { return internal_to_external_; }
140140 const auto & internalToExternalMap () const { return internal_to_external_; }
141141
142+ // set in resolveInterface()
143+ InterfaceFlags required_interface_;
144+
142145private:
143146 container_type children_;
144147
@@ -166,28 +169,20 @@ class SerialContainerPrivate : public ContainerBasePrivate
166169public:
167170 SerialContainerPrivate (SerialContainer* me, const std::string& name);
168171
169- // containers derive their required interface from their children
170- InterfaceFlags requiredInterface () const override ;
171-
172172 // called by parent asking for pruning of this' interface
173- void pruneInterface (InterfaceFlags accepted ) override ;
173+ void resolveInterface (InterfaceFlags expected ) override ;
174174 // validate connectivity of chain
175175 void validateConnectivity () const override ;
176176
177- private:
178- // connect cur stage to its predecessor and successor
179- bool connect (container_type::const_iterator cur);
177+ void reset ();
180178
181- // called by init() to prune interfaces for children in range [first, last)
182- void pruneInterfaces (container_type::const_iterator first, container_type::const_iterator end);
183- // prune interface for children in range [first, last) to given direction
184- void pruneInterfaces (container_type::const_iterator first, container_type::const_iterator end,
185- InterfaceFlags accepted);
186- // store first/last child's interface as required for this container
187- void storeRequiredInterface (container_type::const_iterator first, container_type::const_iterator end);
179+ protected:
180+ // connect two neighbors
181+ void connect (StagePrivate& stage1, StagePrivate& stage2);
188182
189- private:
190- InterfaceFlags required_interface_;
183+ // validate that child's interface matches mine (considering start or end only as determined by mask)
184+ template <unsigned int mask>
185+ void validateInterface (const StagePrivate& child, InterfaceFlags required) const ;
191186};
192187PIMPL_FUNCTIONS (SerialContainer)
193188
@@ -219,14 +214,14 @@ class ParallelContainerBasePrivate : public ContainerBasePrivate
219214public:
220215 ParallelContainerBasePrivate (ParallelContainerBase* me, const std::string& name);
221216
222- // containers derive their required interface from their children
223- InterfaceFlags requiredInterface () const override ;
224-
225217 // called by parent asking for pruning of this' interface
226- void pruneInterface (InterfaceFlags accepted ) override ;
218+ void resolveInterface (InterfaceFlags expected ) override ;
227219
228220 void validateConnectivity () const override ;
229221
222+ protected:
223+ void validateInterfaces (const StagePrivate& child, InterfaceFlags& external, bool first = false ) const ;
224+
230225private:
231226 // / callback for new externally received states
232227 void onNewExternalState (Interface::Direction dir, Interface::iterator external, bool updated);
@@ -256,7 +251,7 @@ class MergerPrivate : public ParallelContainerBasePrivate
256251 typedef std::function<void (SubTrajectory&&)> Spawner;
257252 MergerPrivate (Merger* me, const std::string& name);
258253
259- InterfaceFlags requiredInterface () const override ;
254+ void resolveInterface (InterfaceFlags expected) override ;
260255
261256 void onNewPropagateSolution (const SolutionBase& s);
262257 void onNewGeneratorSolution (const SolutionBase& s);
0 commit comments