Skip to content

Commit

Permalink
Implement FallbacksPrivate[Propagator|Connect] with common template
Browse files Browse the repository at this point in the history
  • Loading branch information
rhaschke committed Nov 25, 2021
1 parent 4de07f3 commit 1468a94
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 74 deletions.
34 changes: 26 additions & 8 deletions core/include/moveit/task_constructor/container_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,10 @@ class FallbacksPrivate : public ParallelContainerBasePrivate
/// Advance to the next job, assuming that the current child is exhausted on the current job.
virtual bool nextJob() { return false; }
/// Reset data structures
virtual void reset();
virtual void reset() {
current_ = children().begin();
job_has_solutions_ = false;
}

container_type::const_iterator current_; // currently active child generator
bool job_has_solutions_; // flag indicating whether the current job generated solutions
Expand All @@ -281,25 +284,40 @@ struct FallbacksPrivateGenerator : FallbacksPrivate
struct FallbacksPrivatePropagator : FallbacksPrivate
{
FallbacksPrivatePropagator(FallbacksPrivate&& old);
bool nextJob() override;
void reset() override;

using JobType = Interface::iterator;
inline auto& pendingJobs() { return *pullInterface(dir_); }
inline bool isFeasible(JobType job) { return job->priority().enabled(); }
inline void deactivateJob(JobType job) {}
inline void activateJob(JobType job);
Interface::Direction dir_; // propagation direction
Interface::iterator job_; // pointer to currently processed external state
};

/// Fallbacks implementation for CONNECT interface
struct FallbacksPrivateConnect : ConnectingShared, FallbacksPrivate
{
FallbacksPrivateConnect(FallbacksPrivate&& old);
bool nextJob() override;
void reset() override;

using JobType = ConnectingShared::container_type::iterator;
inline auto& pendingJobs() { return pending_; }
inline bool isFeasible(JobType job) { return job->first->priority().enabled() && job->second->priority().enabled(); }
inline void deactivateJob(JobType job);
inline void activateJob(JobType job);

template <Interface::Direction dir>
void pushState(Interface::iterator external, InterfaceState::Status status);
};

/// Generic job-based Fallbacks implementation for PROPAGATE and CONNECT interfaces
template <typename T>
struct FallbacksPrivateJobBased : T
{
using BaseType = T;
FallbacksPrivateJobBased(FallbacksPrivate&& old);
bool nextJob() override;
void reset() override;

// pointer to currently processed pair of external states
ConnectingShared::container_type::iterator job_;
typename BaseType::JobType job_; // currently processed job
};

class WrapperBasePrivate : public ParallelContainerBasePrivate
Expand Down
3 changes: 2 additions & 1 deletion core/include/moveit/task_constructor/storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ class Interface : public ordered<InterfaceState*>

/// remove a state from the interface and return it as a one-element list
container_type remove(iterator it);
// alias for use with templates (TODO: replace remove())
inline container_type erase(iterator it) { return remove(it); }

/// update state's priority (and call notify_ if it really has changed)
void updatePriority(InterfaceState* state, const InterfaceState::Priority& priority);
Expand All @@ -211,7 +213,6 @@ class Interface : public ordered<InterfaceState*>

// restrict access to some functions to ensure consistency
// (we need to set/unset InterfaceState::owner_)
using base_type::erase;
using base_type::insert;
using base_type::moveFrom;
using base_type::moveTo;
Expand Down
102 changes: 37 additions & 65 deletions core/src/container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -886,10 +886,10 @@ inline void Fallbacks::replaceImpl() {
break;
case PROPAGATE_FORWARDS:
case PROPAGATE_BACKWARDS:
impl = new FallbacksPrivatePropagator(std::move(*impl));
impl = new FallbacksPrivateJobBased<FallbacksPrivatePropagator>(std::move(*impl));
break;
case CONNECT:
impl = new FallbacksPrivateConnect(std::move(*impl));
impl = new FallbacksPrivateJobBased<FallbacksPrivateConnect>(std::move(*impl));
break;
}
delete pimpl_;
Expand All @@ -905,11 +905,6 @@ FallbacksPrivate::FallbacksPrivate(FallbacksPrivate&& other)
this->ParallelContainerBasePrivate::operator=(std::move(other));
}

void FallbacksPrivate::reset() {
current_ = children().begin();
job_has_solutions_ = false;
}

void FallbacksPrivate::initializeExternalInterfaces() {
// Here we know the final interface of the container (and all its children)
// Thus replace, this pimpl() with a new interface-specific one:
Expand Down Expand Up @@ -948,7 +943,6 @@ bool FallbacksPrivateGenerator::nextJob() {
return current_ != children().end();
}


FallbacksPrivatePropagator::FallbacksPrivatePropagator(FallbacksPrivate&& old)
: FallbacksPrivate(std::move(old)) {
switch (requiredInterface()) {
Expand All @@ -963,58 +957,18 @@ FallbacksPrivatePropagator::FallbacksPrivatePropagator(FallbacksPrivate&& old)
default:
assert(false);
}
FallbacksPrivatePropagator::reset();
}

void FallbacksPrivatePropagator::reset() {
FallbacksPrivate::reset();
job_ = pullInterface(dir_)->end(); // indicate fresh start
}

bool FallbacksPrivatePropagator::nextJob() {
assert(current_ != children().end() && !(*current_)->pimpl()->canCompute());
const auto jobs = pullInterface(dir_);

if (job_ != jobs->end()) { // current job exists, but is exhausted on current child
if (!job_has_solutions_) // job didn't produce solutions -> feed to next child
nextChild();
else
current_ = children().end(); // indicate that this job is exhausted on all children
}
job_has_solutions_ = false;

if (current_ == children().end()) { // all children processed the job_
if (job_ != jobs->end()) {
jobs->remove(job_); // we don't need the job in our interface list anymore
job_ = jobs->end(); // indicate that we need to fetch a new job
}
current_ = children().begin(); // start next job with first child again
}

// pick next job if needed and possible
if (job_ == jobs->end()) { // need to pick next job
if (!jobs->empty() && jobs->front()->priority().enabled())
job_ = jobs->begin();
else
return false; // no more jobs available
}

void FallbacksPrivatePropagator::activateJob(JobType job) {
// When arriving here, we have a valid job_ and a current_ child to feed it. Let's do that.
copyState(dir_, job_, (*current_)->pimpl()->pullInterface(dir_), false);
return true;
copyState(dir_, job, (*current_)->pimpl()->pullInterface(dir_), false);
}

FallbacksPrivateConnect::FallbacksPrivateConnect(FallbacksPrivate&& old)
: FallbacksPrivate(std::move(old)) {
starts_ = std::make_shared<Interface>();
ends_ = std::make_shared<Interface>();
ConnectingShared::initInterfaces(starts_, ends_);
FallbacksPrivateConnect::reset();
}

void FallbacksPrivateConnect::reset() {
FallbacksPrivate::reset();
job_ = pending_.end(); // indicate fresh start
}

template <Interface::Direction dir>
Expand All @@ -1035,38 +989,56 @@ void FallbacksPrivateConnect::pushState(Interface::iterator external, InterfaceS
/* CONNECT-like stages are tricky, because we need to consider each pair of (start, end) states and
feed them one by one to all children.
TODO: To activate only a single pair at a time, we need to disable currently active (start, end) states. */
bool FallbacksPrivateConnect::nextJob() {
assert(current_ != children().end() && !(*current_)->pimpl()->canCompute());
auto& jobs = pending_;
void FallbacksPrivateConnect::deactivateJob(JobType job) {
}
void FallbacksPrivateConnect::activateJob(JobType job) {
pushState<Interface::Direction::FORWARD>(job->first, InterfaceState::Status::ENABLED);
pushState<Interface::Direction::BACKWARD>(job->second, InterfaceState::Status::ENABLED);
}

template <typename T>
FallbacksPrivateJobBased<T>::FallbacksPrivateJobBased(FallbacksPrivate&& old)
: T(std::move(old)) {
FallbacksPrivateJobBased<T>::reset();
}

template <typename T>
void FallbacksPrivateJobBased<T>::reset() {
BaseType::reset();
job_ = this->pendingJobs().end(); // indicate fresh start
}

template <typename T>
bool FallbacksPrivateJobBased<T>::nextJob() {
assert(this->current_ != this->children().end() && !(*this->current_)->pimpl()->canCompute());
auto& jobs = this->pendingJobs();

if (job_ != jobs.end()) { // current job exists, but is exhausted on current child
if (!job_has_solutions_) // job didn't produce solutions -> feed to next child
nextChild();
if (!this->job_has_solutions_) // job didn't produce solutions -> feed to next child
this->nextChild();
else
current_ = children().end(); // indicate that this job is exhausted on all children
this->current_ = this->children().end(); // indicate that this job is exhausted on all children
}
job_has_solutions_ = false;
this->job_has_solutions_ = false;

if (current_ == children().end()) { // all children processed the job_
if (this->current_ == this->children().end()) { // all children processed the job_
if (job_ != jobs.end()) {
jobs.erase(job_); // we don't need the job in our interface list anymore
this->deactivateJob(job_);
jobs.erase(job_); // we don't need the job in our job list anymore
job_ = jobs.end(); // indicate that we need to fetch a new job
}
current_ = children().begin(); // start next job with first child again
this->current_ = this->children().begin(); // start next job with first child again
}

// pick next job if needed and possible
if (job_ == jobs.end()) { // need to pick next job
if (!jobs.empty() && jobs.front().first->priority().enabled() &&
jobs.front().second->priority().enabled())
if (!jobs.empty() && this->isFeasible(jobs.begin()))
job_ = jobs.begin();
else
return false; // no more jobs available
}

// When arriving here, we have a valid job_ and a current_ child to feed it. Let's do that.
pushState<Interface::Direction::FORWARD>(job_->first, InterfaceState::Status::ENABLED);
pushState<Interface::Direction::BACKWARD>(job_->second, InterfaceState::Status::ENABLED);
this->activateJob(job_);
return true;
}

Expand Down

0 comments on commit 1468a94

Please sign in to comment.