* constructor.
*/
Synchronized() = default;
- /**
+ /**
* Copy constructor copies the data (with locking the source and
* all) but does NOT copy the mutex. Doing so would result in
* deadlocks.
* Constructor taking a datum rvalue as argument moves it. Again,
* there is no need to lock the constructing object.
*/
- explicit Synchronized(T && rhs) : datum_(std::move(rhs)) {}
+ explicit Synchronized(T&& rhs) : datum_(std::move(rhs)) {}
/**
* The canonical assignment operator only assigns the data, NOT the
* addresses.
*/
Synchronized& operator=(const Synchronized& rhs) {
- if (this < *rhs) {
+ if (this == &rhs) {
+ // Self-assignment, pass.
+ } else if (this < &rhs) {
auto guard1 = operator->();
auto guard2 = rhs.operator->();
datum_ = rhs.datum_;
return *this;
}
+ /**
+ * Move assignment operator, only assigns the data, NOT the
+ * mutex. It locks the two objects in ascending order of their
+ * addresses.
+ */
+ Synchronized& operator=(Synchronized&& rhs) {
+ if (this == &rhs) {
+ // Self-assignment, pass.
+ } else if (this < &rhs) {
+ auto guard1 = operator->();
+ auto guard2 = rhs.operator->();
+ datum_ = std::move(rhs.datum_);
+ } else {
+ auto guard1 = rhs.operator->();
+ auto guard2 = operator->();
+ datum_ = std::move(rhs.datum_);
+ }
+ return *this;
+ }
+
/**
* Lock object, assign datum.
*/
return *this;
}
+ /**
+ * Lock object, move-assign datum.
+ */
+ Synchronized& operator=(T&& rhs) {
+ auto guard = operator->();
+ datum_ = std::move(rhs);
+ return *this;
+ }
+
/**
* A LockedPtr lp keeps a modifiable (i.e. non-const)
* Synchronized<T> object locked for the duration of lp's
}
auto guard1 = operator->();
auto guard2 = rhs.operator->();
- datum_.swap(rhs.datum_);
+
+ using std::swap;
+ swap(datum_, rhs.datum_);
}
/**
*/
void swap(T& rhs) {
LockedPtr guard = operator->();
- datum_.swap(rhs);
+
+ using std::swap;
+ swap(datum_, rhs);
}
/**