Make tensorflow::Status movable.

PiperOrigin-RevId: 281542191
Change-Id: Ia9e8f3078526fa45228e10c194e5d962d3103bcc
This commit is contained in:
A. Unique TensorFlower 2019-11-20 09:58:42 -08:00 committed by TensorFlower Gardener
parent 2526bdf63f
commit 636267689b
4 changed files with 40 additions and 7 deletions

View File

@ -47,7 +47,11 @@ class Status {
/// Copy the specified status.
Status(const Status& s);
void operator=(const Status& s);
Status& operator=(const Status& s);
#ifndef SWIG
Status(Status&& s) noexcept;
Status& operator=(Status&& s) noexcept;
#endif // SWIG
static Status OK() { return Status(); }
@ -133,16 +137,28 @@ class StatusGroup {
};
inline Status::Status(const Status& s)
: state_((s.state_ == NULL) ? NULL : new State(*s.state_)) {}
: state_((s.state_ == nullptr) ? nullptr : new State(*s.state_)) {}
inline void Status::operator=(const Status& s) {
inline Status& Status::operator=(const Status& s) {
// The following condition catches both aliasing (when this == &s),
// and the common case where both s and *this are ok.
if (state_ != s.state_) {
SlowCopyFrom(s.state_.get());
}
return *this;
}
#ifndef SWIG
inline Status::Status(Status&& s) noexcept : state_(std::move(s.state_)) {}
inline Status& Status::operator=(Status&& s) noexcept {
if (state_ != s.state_) {
state_ = std::move(s.state_);
}
return *this;
}
#endif // SWIG
inline bool Status::operator==(const Status& x) const {
return (this->state_ == x.state_) || (ToString() == x.ToString());
}

View File

@ -58,6 +58,19 @@ TEST(Status, Assign) {
ASSERT_EQ(a.ToString(), b.ToString());
}
TEST(Status, Move) {
Status a(errors::InvalidArgument("Invalid"));
Status b(std::move(a));
ASSERT_EQ("Invalid argument: Invalid", b.ToString());
}
TEST(Status, MoveAssign) {
Status a(errors::InvalidArgument("Invalid"));
Status b;
b = std::move(a);
ASSERT_EQ("Invalid argument: Invalid", b.ToString());
}
TEST(Status, Update) {
Status s;
s.Update(Status::OK());

View File

@ -273,7 +273,9 @@ const Status& StatusOr<T>::status() const & {
}
template <typename T>
Status StatusOr<T>::status() && {
return ok() ? Status::OK() : std::move(this->status_);
// Note that we copy instead of moving the status here so that
// ~StatusOrData() can call ok() without invoking UB.
return ok() ? Status::OK() : this->status_;
}
template <typename T>

View File

@ -67,7 +67,7 @@ class StatusOrData {
MakeValue(std::move(other.data_));
MakeStatus();
} else {
MakeStatus(std::move(other.status_));
MakeStatus(other.status_);
}
}
@ -87,7 +87,7 @@ class StatusOrData {
MakeValue(std::move(other.data_));
MakeStatus();
} else {
MakeStatus(std::move(other.status_));
MakeStatus(other.status_);
}
}
@ -156,7 +156,9 @@ class StatusOrData {
void Assign(Status&& status) {
Clear();
status_ = std::move(status);
// Note that we copy instead of moving the status here so that
// status.~StatusOrData() can call ok() without invoking UB.
status_ = status;
EnsureNotOk();
}