Skip to content

Commit df8a783

Browse files
committed
enforce one-parent policy in StagePrivate
So new containers cannot get this wrong by accident.
1 parent 90f5d22 commit df8a783

File tree

3 files changed

+37
-15
lines changed

3 files changed

+37
-15
lines changed

core/include/moveit/task_constructor/stage_p.h

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@
4141
#include <moveit/task_constructor/stage.h>
4242
#include <moveit/task_constructor/storage.h>
4343
#include <moveit/task_constructor/cost_queue.h>
44+
45+
#include <ros/ros.h>
46+
4447
#include <ostream>
4548
#include <chrono>
4649

@@ -112,15 +115,31 @@ class StagePrivate
112115
return dir == Interface::FORWARD ? next_starts_.lock() : prev_ends_.lock();
113116
}
114117

115-
/// the following methods should be called only by a container
116-
/// to setup the connection structure of their children
117-
inline void setHierarchy(ContainerBase* parent, container_type::iterator it) {
118+
/// set parent of stage
119+
/// enforce only one parent exists
120+
inline bool setParent(ContainerBase* parent) {
121+
if (parent_) {
122+
ROS_ERROR_STREAM("Tried to add stage '" << name() << "' to two parents");
123+
return false; // it's not allowed to add a stage to a parent if it already has one
124+
}
118125
parent_ = parent;
119-
it_ = it;
126+
return true;
127+
}
128+
129+
/// explicitly orphan stage
130+
inline void unparent() {
131+
parent_ = nullptr;
132+
it_ = container_type::iterator();
120133
}
134+
135+
/// the following methods should be called only by the current parent
136+
/// to setup the connection structure of their children
137+
inline void setParentPosition(container_type::iterator it) { it_ = it; }
138+
inline void setIntrospection(Introspection* introspection) { introspection_ = introspection; }
139+
121140
inline void setPrevEnds(const InterfacePtr& prev_ends) { prev_ends_ = prev_ends; }
122141
inline void setNextStarts(const InterfacePtr& next_starts) { next_starts_ = next_starts; }
123-
inline void setIntrospection(Introspection* introspection) { introspection_ = introspection; }
142+
124143
void composePropertyErrorMsg(const std::string& name, std::ostream& os);
125144

126145
// methods to spawn new solutions

core/src/container.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,22 +196,19 @@ bool ContainerBase::traverseRecursively(const ContainerBase::StageCallback& proc
196196

197197
bool ContainerBase::insert(Stage::pointer&& stage, int before) {
198198
StagePrivate* impl = stage->pimpl();
199-
if (impl->parent() != nullptr || !stage->solutions().empty() || !stage->failures().empty()) {
200-
ROS_ERROR("cannot re-parent stage");
199+
if (!impl->setParent(this))
201200
return false;
202-
}
203-
204201
ContainerBasePrivate::const_iterator where = pimpl()->childByIndex(before, true);
205202
ContainerBasePrivate::iterator it = pimpl()->children_.insert(where, std::move(stage));
206-
impl->setHierarchy(this, it);
203+
impl->setParentPosition(it);
207204
return true;
208205
}
209206

210207
bool ContainerBasePrivate::remove(ContainerBasePrivate::const_iterator pos) {
211208
if (pos == children_.end())
212209
return false;
213210

214-
(*pos)->pimpl()->setHierarchy(nullptr, ContainerBasePrivate::iterator());
211+
(*pos)->pimpl()->unparent();
215212
children_.erase(pos);
216213
return true;
217214
}

core/src/task.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,18 @@ void swap(StagePrivate*& lhs, StagePrivate*& rhs) {
8686

8787
// and redirect the parent pointers of children to new parents
8888
auto& lhs_children = static_cast<ContainerBasePrivate*>(lhs)->children_;
89-
for (auto it = lhs_children.begin(), end = lhs_children.end(); it != end; ++it)
90-
(*it)->pimpl()->setHierarchy(static_cast<ContainerBase*>(lhs->me_), it);
89+
for (auto it = lhs_children.begin(), end = lhs_children.end(); it != end; ++it) {
90+
(*it)->pimpl()->unparent();
91+
(*it)->pimpl()->setParent(static_cast<ContainerBase*>(lhs->me_));
92+
(*it)->pimpl()->setParentPosition(it);
93+
}
9194

9295
auto& rhs_children = static_cast<ContainerBasePrivate*>(rhs)->children_;
93-
for (auto it = rhs_children.begin(), end = rhs_children.end(); it != end; ++it)
94-
(*it)->pimpl()->setHierarchy(static_cast<ContainerBase*>(rhs->me_), it);
96+
for (auto it = rhs_children.begin(), end = rhs_children.end(); it != end; ++it) {
97+
(*it)->pimpl()->unparent();
98+
(*it)->pimpl()->setParent(static_cast<ContainerBase*>(rhs->me_));
99+
(*it)->pimpl()->setParentPosition(it);
100+
}
95101
}
96102

97103
const ContainerBase* TaskPrivate::stages() const {

0 commit comments

Comments
 (0)