proposal to include "operator dist_object<T>::bool() const" that returns true normally but false for invalid dist_objects.
When a dist_object is moved, the specs state that it is invalidated, so it would be helpful to provide an interface to detect this condition.
template <typename T> dist_object<T>::dist_object(dist_object<T> &&other);
Precondition: Calling thread must have the master persona.
Makes this instance the calling process’s representative of the distributed object associated with other, transferring all state from other. Invalidates other, and any subsequent operations on other, except for destruction, produce undefined behavior.
Since a dist_object behaves mostly like a pointer it would be nice to test for its validity like it is possible with nullptr and shared_ptr, especially in the destructor of classes that include a dist_object as a member and want, themselves, to support the move constructor properly.
usage:
dist_object<int> d_o(world());
assert(d_o);
dist_object<int> d_o2(std::move(d_o));
assert(d_o2);
assert(!d_o);
Class My {
dist_object<int> my_do;
public:
My
: my_do(world())
{}
My(My &&mv)
: my_do(std::move(mv.my_do))
{}
My(const My &cp) = delete;
~My() {
if(my_do) {
// do some teardown with my_do
}
}
};
Comments (5)
-
-
- changed milestone to 2021.3.0 release
Mass roll-over of open issues to next release milestone
-
- changed milestone to 2021.9.0 release
- changed version to Development branch (master)
Mass roll-over of open issues to next release milestone
-
Unlike
std::shared_ptr
, there isn’t a mechanism for constructing an “empty”dist_object
, nor do we have semantics for what operations would be valid on such adist_object
. So I don’t think the two are analogous. -
- changed status to wontfix
This was discussed in the 2021-04-17 Pagoda meeting.
Standard C++ practice is to avoid relying on the value of a moved-from object, and we agreed that we don't want to encourage that behavior in UPC++.
- Log in to comment
As a general principle, I don't like the idea of an implicit conversion to
bool
for a container - that introduces too much danger of misuse if someone has adist_object<bool> mydo
and accidentally typesmydo
when then mean*mydo
. Setting syntax aside for now...I disagree with the premise here. Syntax aside,
dist_object<T>
does not have pointer-like semantics. It is a non-copyable, non-default-constructible object containing an unboxedT
value. The fact there is adist_id
that can be used to locate a reference to the current instance in an implicit registry does not change the fact that adist_object<T>
instance is a non-copyable unboxed container. If anythingdist_object<T>
behaves more like a specialstd::tuple<T>
than a pointer toT
.It's true that moving a
dist_object
"invalidates" the source instance (making it no longer the registered local representative instance), but that's not analogous to a nulled pointer - in particular, the containedT
in the source instance still exists, as a post-moved object that has not yet been destroyed. In retrospect, the move semantics should probably say it "deregisters" the source instance rather than "invalidates" it. The "invalid" term conflates with other degenerate states like post-destruction or uninitialized memory, which are not what we mean here.With regards to the specific example - a
dist_object
move also moves the wrapped value. So I think you can get the effect you are looking for by keeping a "is_moved" or "is_move_invalidated" state bit in your wrapped object (in this caseint
) or in the containing class (in this caseMy
), either of which can track the move equally well. I understand the need to track "liveness" in theMy
class (in order to correctly implement move/destroy semantics), but I don't love the idea of co-optingdist_object
to serve this "liveness flag" purpose. If nothing else it breaks the design principle that the source object of a move should only be passed to the destructor and no other calls.Re-reading the spec for dist_object I see some of the details here are a bit unclear, so I've just opened PR 60 to fix that.