@@ -112,28 +112,6 @@ InterfaceFlags StagePrivate::interfaceFlags() const {
112112 return f;
113113}
114114
115- void StagePrivate::pruneInterface (InterfaceFlags accepted) {
116- const InterfaceFlags accepted_start{ accepted & START_IF_MASK };
117- const InterfaceFlags accepted_end{ accepted & END_IF_MASK };
118-
119- const InterfaceFlags required{ requiredInterface () };
120- const InterfaceFlags required_start{ required & START_IF_MASK };
121- const InterfaceFlags required_end{ required & END_IF_MASK };
122-
123- if (required == UNKNOWN)
124- throw std::logic_error (" stage type does not specify interface, but also does not override pruneInterface. "
125- " Who sets up its interfaces?" );
126-
127- // only one side needs to be specified but the value has to be compatible with this stage
128- if (((accepted_start != UNKNOWN) && (accepted_start & required_start) != required_start) ||
129- ((accepted_end != UNKNOWN) && (accepted_end & required_end) != required_end)) {
130- boost::format desc (" interface %1% %2% does not match inferred interface %3% %4%" );
131- desc % flowSymbol<START_IF_MASK>(required_start) % flowSymbol<END_IF_MASK>(required_end);
132- desc % flowSymbol<START_IF_MASK>(accepted_start) % flowSymbol<END_IF_MASK>(accepted_end);
133- throw InitStageException (*me (), desc.str ());
134- }
135- }
136-
137115void StagePrivate::validateConnectivity () const {
138116 // check that the required interface is provided
139117 InterfaceFlags required = requiredInterface ();
@@ -416,47 +394,53 @@ ComputeBase::ComputeBase(ComputeBasePrivate* impl) : Stage(impl) {}
416394
417395PropagatingEitherWayPrivate::PropagatingEitherWayPrivate (PropagatingEitherWay* me, PropagatingEitherWay::Direction dir,
418396 const std::string& name)
419- : ComputeBasePrivate(me, name), required_interface_dirs_(dir) {}
397+ : ComputeBasePrivate(me, name), configured_dir_(dir) {
398+ initInterface (dir);
399+ }
420400
421401// initialize pull interfaces to match requested propagation directions
422402void PropagatingEitherWayPrivate::initInterface (PropagatingEitherWay::Direction dir) {
423- if (required_interface_dirs_ != PropagatingEitherWay::AUTO && dir != required_interface_dirs_) {
424- auto flow = [](PropagatingEitherWay::Direction dir) -> const char * {
425- switch (dir) {
426- case PropagatingEitherWay::AUTO:
427- return flowSymbol<START_IF_MASK>(InterfaceFlags{ READS_START, WRITES_PREV_END });
428- case PropagatingEitherWay::FORWARD:
429- return flowSymbol<START_IF_MASK>(InterfaceFlags{ READS_START });
430- case PropagatingEitherWay::BACKWARD:
431- return flowSymbol<START_IF_MASK>(InterfaceFlags{ WRITES_PREV_END });
432- }
433- };
434-
435- boost::format desc (" propagation direction %1% incompatible with inferred direction %2%" );
436- desc % flow (required_interface_dirs_) % flow (dir);
437- throw InitStageException (*me (), desc.str ());
403+ switch (dir) {
404+ case PropagatingEitherWay::FORWARD:
405+ required_interface_ = PROPAGATE_FORWARDS;
406+ if (!starts_) // keep existing interface if possible
407+ starts_.reset (
408+ new Interface ([this ](Interface::iterator it, bool /* updated*/ ) { this ->dropFailedStarts (it); }));
409+ ends_.reset ();
410+ return ;
411+ case PropagatingEitherWay::BACKWARD:
412+ required_interface_ = PROPAGATE_BACKWARDS;
413+ starts_.reset ();
414+ if (!ends_) // keep existing interface if possible
415+ ends_.reset (new Interface ([this ](Interface::iterator it, bool /* updated*/ ) { this ->dropFailedEnds (it); }));
416+ return ;
417+ case PropagatingEitherWay::AUTO:
418+ required_interface_ = UNKNOWN;
419+ return ;
438420 }
439-
440- if (dir == PropagatingEitherWay::FORWARD)
441- starts_.reset (new Interface ([this ](Interface::iterator it, bool /* updated */ ) { this ->dropFailedStarts (it); }));
442- else if (dir == PropagatingEitherWay::BACKWARD)
443- ends_.reset (new Interface ([this ](Interface::iterator it, bool /* updated */ ) { this ->dropFailedEnds (it); }));
444-
445- required_interface_dirs_ = dir;
446421}
447422
448423void PropagatingEitherWayPrivate::pruneInterface (InterfaceFlags accepted) {
449424 if (accepted == UNKNOWN)
450- throw InitStageException (*me (), " cannot prune to unknown interface" );
425+ throw InitStageException (*me (), " cannot initialize to unknown interface" );
426+
427+ auto dir = PropagatingEitherWay::AUTO;
451428 if ((accepted & START_IF_MASK) == READS_START || (accepted & END_IF_MASK) == WRITES_NEXT_START)
452- initInterface ( PropagatingEitherWay::FORWARD) ;
429+ dir = PropagatingEitherWay::FORWARD;
453430 else if ((accepted & START_IF_MASK) == WRITES_PREV_END || (accepted & END_IF_MASK) == READS_END)
454- initInterface ( PropagatingEitherWay::BACKWARD) ;
431+ dir = PropagatingEitherWay::BACKWARD;
455432 else {
456- boost::format desc (" propagator cannot act with interfaces start(%1%), end(%2%)" );
433+ boost::format desc (" propagator cannot handle external interface %1% %2%" );
434+ desc % flowSymbol<START_IF_MASK>(accepted) % flowSymbol<END_IF_MASK>(accepted);
435+ throw InitStageException (*me (), desc.str ());
436+ }
437+ if (configured_dir_ != PropagatingEitherWay::AUTO && dir != configured_dir_) {
438+ boost::format desc (" configured interface (%1% %2%) does not match external one (%3% %4%)" );
439+ desc % flowSymbol<START_IF_MASK>(required_interface_) % flowSymbol<END_IF_MASK>(required_interface_);
457440 desc % flowSymbol<START_IF_MASK>(accepted) % flowSymbol<END_IF_MASK>(accepted);
458441 throw InitStageException (*me (), desc.str ());
459442 }
443+ initInterface (dir);
460444}
461445
462446void PropagatingEitherWayPrivate::validateConnectivity () const {
@@ -475,14 +459,7 @@ void PropagatingEitherWayPrivate::validateConnectivity() const {
475459}
476460
477461InterfaceFlags PropagatingEitherWayPrivate::requiredInterface () const {
478- switch (required_interface_dirs_) {
479- case PropagatingEitherWay::FORWARD:
480- return PROPAGATE_FORWARDS;
481- case PropagatingEitherWay::BACKWARD:
482- return PROPAGATE_BACKWARDS;
483- case PropagatingEitherWay::AUTO:
484- return UNKNOWN;
485- }
462+ return required_interface_;
486463}
487464
488465void PropagatingEitherWayPrivate::dropFailedStarts (Interface::iterator state) {
@@ -540,9 +517,11 @@ PropagatingEitherWay::PropagatingEitherWay(PropagatingEitherWayPrivate* impl) :
540517
541518void PropagatingEitherWay::restrictDirection (PropagatingEitherWay::Direction dir) {
542519 auto impl = pimpl ();
543- if (impl->required_interface_dirs_ != AUTO)
520+ if (impl->configured_dir_ == dir)
521+ return ;
522+ if (impl->configured_dir_ != AUTO)
544523 throw std::runtime_error (" Cannot change direction after being connected" );
545-
524+ impl-> configured_dir_ = dir;
546525 impl->initInterface (dir);
547526}
548527
0 commit comments