@@ -76,8 +76,7 @@ namespace task_constructor {
7676class ContainerBasePrivate : public StagePrivate
7777{
7878 friend class ContainerBase ;
79- friend class ConnectingPrivate ; // needs to call protected setStatus()
80- friend void swap (StagePrivate*& lhs, StagePrivate*& rhs);
79+ friend class ConnectingPrivate ; // needed propagate setStatus() in newState()
8180
8281public:
8382 using container_type = StagePrivate::container_type;
@@ -132,10 +131,11 @@ class ContainerBasePrivate : public StagePrivate
132131 inline const auto & externalToInternalMap () const { return internal_external_.by <EXTERNAL>(); }
133132
134133 // / called by a (direct) child when a solution failed
135- void onNewFailure (const Stage& child, const InterfaceState* from, const InterfaceState* to);
134+ virtual void onNewFailure (const Stage& child, const InterfaceState* from, const InterfaceState* to);
136135
137136protected:
138137 ContainerBasePrivate (ContainerBase* me, const std::string& name);
138+ ContainerBasePrivate& operator =(ContainerBasePrivate&& other);
139139
140140 // Set child's push interfaces: allow pushing if child requires it.
141141 inline void setChildsPushBackwardInterface (StagePrivate* child) {
@@ -154,10 +154,14 @@ class ContainerBasePrivate : public StagePrivate
154154 void setStatus (const Stage* creator, const InterfaceState* source, const InterfaceState* target,
155155 InterfaceState::Status status);
156156
157- // / copy external_state to a child's interface and remember the link in internal_external map
157+ // / Copy external_state to a child's interface and remember the link in internal_external map
158158 template <Interface::Direction>
159159 void copyState (Interface::iterator external, const InterfacePtr& target, Interface::UpdateFlags updated);
160- // / lift solution from internal to external level
160+ // non-template version
161+ void copyState (Interface::Direction dir, Interface::iterator external, const InterfacePtr& target,
162+ Interface::UpdateFlags updated);
163+
164+ // / Lift solution from internal to external level
161165 void liftSolution (const SolutionBasePtr& solution, const InterfaceState* internal_from,
162166 const InterfaceState* internal_to);
163167
@@ -230,12 +234,91 @@ class ParallelContainerBasePrivate : public ContainerBasePrivate
230234 void validateInterfaces (const StagePrivate& child, InterfaceFlags& external, bool first = false ) const ;
231235
232236private:
233- // / notify callback for new externally received states
237+ // / notify callback for new externally received interface states
234238 template <typename Interface::Direction>
235- void onNewExternalState (Interface::iterator external, Interface::UpdateFlags updated);
239+ void propagateStateToAllChildren (Interface::iterator external, Interface::UpdateFlags updated);
240+
241+ // override to customize behavior on received interface states (default: propagateStateToAllChildren())
242+ virtual void initializeExternalInterfaces ();
236243};
237244PIMPL_FUNCTIONS (ParallelContainerBase)
238245
246+ /* The Fallbacks container needs to implement different behaviour based on its interface.
247+ * Thus, we implement 3 different classes: for Generator, Propagator, and Connect-like interfaces.
248+ * FallbacksPrivate is the common base class for all of them, defining the common API
249+ * to be used by the Fallbacks container.
250+ * The actual interface-specific class is instantiated in initializeExternalInterfaces()
251+ * resp. Fallbacks::replaceImpl() when the actual interface is known.
252+ * The key difference between the 3 variants is how they advance to the next job. */
253+ class FallbacksPrivate : public ParallelContainerBasePrivate
254+ {
255+ public:
256+ FallbacksPrivate (Fallbacks* me, const std::string& name);
257+ FallbacksPrivate (FallbacksPrivate&& other);
258+
259+ void initializeExternalInterfaces () final ;
260+ void onNewFailure (const Stage& child, const InterfaceState* from, const InterfaceState* to) override ;
261+
262+ // virtual methods specific to each variant
263+ virtual void onNewSolution (const SolutionBase& s);
264+ virtual void reset () {}
265+ };
266+ PIMPL_FUNCTIONS (Fallbacks)
267+
268+ /* Class shared between FallbacksPrivateGenerator and FallbacksPrivatePropagator,
269+ which both have the notion of a currently active child stage */
270+ class FallbacksPrivateCommon : public FallbacksPrivate
271+ {
272+ public:
273+ FallbacksPrivateCommon (FallbacksPrivate&& other) : FallbacksPrivate(std::move(other)) {}
274+
275+ // / Advance to next child
276+ inline void nextChild ();
277+ // / Advance to the next job, assuming that the current child is exhausted on the current job.
278+ virtual bool nextJob () = 0;
279+
280+ void reset () override ;
281+ bool canCompute () const override ;
282+ void compute () override ;
283+
284+ container_type::const_iterator current_; // currently active child
285+ };
286+
287+ // / Fallbacks implementation for GENERATOR interface
288+ struct FallbacksPrivateGenerator : FallbacksPrivateCommon
289+ {
290+ FallbacksPrivateGenerator (FallbacksPrivate&& old);
291+ bool nextJob () override ;
292+ };
293+
294+ // / Fallbacks implementation for FORWARD or BACKWARD interface
295+ struct FallbacksPrivatePropagator : FallbacksPrivateCommon
296+ {
297+ FallbacksPrivatePropagator (FallbacksPrivate&& old);
298+ void reset () override ;
299+ void onNewSolution (const SolutionBase& s) override ;
300+ bool nextJob () override ;
301+
302+ Interface::Direction dir_; // propagation direction
303+ Interface::iterator job_; // pointer to currently processed external state
304+ bool job_has_solutions_; // flag indicating whether the current job generated solutions
305+ };
306+
307+ // / Fallbacks implementation for CONNECT interface
308+ struct FallbacksPrivateConnect : FallbacksPrivate
309+ {
310+ FallbacksPrivateConnect (FallbacksPrivate&& old);
311+ void reset () override ;
312+ bool canCompute () const override ;
313+ void compute () override ;
314+ void onNewFailure (const Stage& child, const InterfaceState* from, const InterfaceState* to) override ;
315+
316+ template <Interface::Direction dir>
317+ void propagateStateUpdate (Interface::iterator external, Interface::UpdateFlags updated);
318+
319+ mutable container_type::const_iterator active_; // child picked for compute()
320+ };
321+
239322class WrapperBasePrivate : public ParallelContainerBasePrivate
240323{
241324 friend class WrapperBase ;
0 commit comments