int62_t: use explicit memory order for all loads and stores
Also, improve implementation of CAS loops for operator <X>=. Ideally, we ought to test this on ARM, both before and after.
This commit is contained in:
parent
fe17b98079
commit
4137271188
@ -59,7 +59,7 @@ class alignas(16) int62_t {
|
||||
|
||||
int62_t () : v (0) {}
|
||||
int62_t (bool bc, int64_t vc) : v (build (bc, vc)) {}
|
||||
int62_t (int62_t const & other) { v.store (other.v.load()); }
|
||||
int62_t (int62_t const & other) { v.store (other.v.load(std::memory_order_acquire), std::memory_order_release); }
|
||||
|
||||
static const int64_t max = 4611686018427387903; /* 2^62 - 1 */
|
||||
static const int64_t min = -2305843009213693952;
|
||||
@ -67,8 +67,8 @@ class alignas(16) int62_t {
|
||||
bool flagged() const { return flagged (v); }
|
||||
int64_t val() const { return int62(v); }
|
||||
|
||||
int62_t& operator= (int64_t n) { v.store (build (flagged (v.load()), n)); return *this; }
|
||||
int62_t& operator= (int62_t const & other) { v.store (other.v.load()); return *this; }
|
||||
int62_t& operator= (int64_t n) { v.store (build (flagged (v.load(std::memory_order_acquire)), n), std::memory_order_release); return *this; }
|
||||
int62_t& operator= (int62_t const & other) { v.store (other.v.load(std::memory_order_acquire), std::memory_order_release); return *this; }
|
||||
|
||||
/* there's a pattern to many of these operators:
|
||||
|
||||
@ -85,19 +85,19 @@ class alignas(16) int62_t {
|
||||
rather than two separate loads for each "part".
|
||||
*/
|
||||
|
||||
int62_t operator- () const { const int64_t vv = v.load(); return int62_t (flagged (vv), -int62(vv)); }
|
||||
int62_t operator- () const { const int64_t vv = v.load(std::memory_order_acquire); return int62_t (flagged (vv), -int62(vv)); }
|
||||
|
||||
int62_t operator+ (int64_t n) const { const int64_t vv = v.load(); return int62_t (flagged (vv), int62 (vv) + n); }
|
||||
int62_t operator- (int64_t n) const { const int64_t vv = v.load(); return int62_t (flagged (vv), int62 (vv) - n); }
|
||||
int62_t operator* (int64_t n) const { const int64_t vv = v.load(); return int62_t (flagged (vv), int62 (vv) * n); }
|
||||
int62_t operator/ (int64_t n) const { const int64_t vv = v.load(); return int62_t (flagged (vv), int62 (vv) / n); }
|
||||
int62_t operator% (int64_t n) const { const int64_t vv = v.load(); return int62_t (flagged (vv), int62 (vv) % n); }
|
||||
int62_t operator+ (int64_t n) const { const int64_t vv = v.load(std::memory_order_acquire); return int62_t (flagged (vv), int62 (vv) + n); }
|
||||
int62_t operator- (int64_t n) const { const int64_t vv = v.load(std::memory_order_acquire); return int62_t (flagged (vv), int62 (vv) - n); }
|
||||
int62_t operator* (int64_t n) const { const int64_t vv = v.load(std::memory_order_acquire); return int62_t (flagged (vv), int62 (vv) * n); }
|
||||
int62_t operator/ (int64_t n) const { const int64_t vv = v.load(std::memory_order_acquire); return int62_t (flagged (vv), int62 (vv) / n); }
|
||||
int62_t operator% (int64_t n) const { const int64_t vv = v.load(std::memory_order_acquire); return int62_t (flagged (vv), int62 (vv) % n); }
|
||||
|
||||
int62_t operator+ (int62_t n) const { const int64_t vv = v.load(); return int62_t (flagged (vv), int62 (vv) + n.val()); }
|
||||
int62_t operator- (int62_t n) const { const int64_t vv = v.load(); return int62_t (flagged (vv), int62 (vv) - n.val()); }
|
||||
int62_t operator* (int62_t n) const { const int64_t vv = v.load(); return int62_t (flagged (vv), int62 (vv) * n.val()); }
|
||||
int62_t operator/ (int62_t n) const { const int64_t vv = v.load(); return int62_t (flagged (vv), int62 (vv) / n.val()); }
|
||||
int62_t operator% (int62_t n) const { const int64_t vv = v.load(); return int62_t (flagged (vv), int62 (vv) % n.val()); }
|
||||
int62_t operator+ (int62_t n) const { const int64_t vv = v.load(std::memory_order_acquire); return int62_t (flagged (vv), int62 (vv) + n.val()); }
|
||||
int62_t operator- (int62_t n) const { const int64_t vv = v.load(std::memory_order_acquire); return int62_t (flagged (vv), int62 (vv) - n.val()); }
|
||||
int62_t operator* (int62_t n) const { const int64_t vv = v.load(std::memory_order_acquire); return int62_t (flagged (vv), int62 (vv) * n.val()); }
|
||||
int62_t operator/ (int62_t n) const { const int64_t vv = v.load(std::memory_order_acquire); return int62_t (flagged (vv), int62 (vv) / n.val()); }
|
||||
int62_t operator% (int62_t n) const { const int64_t vv = v.load(std::memory_order_acquire); return int62_t (flagged (vv), int62 (vv) % n.val()); }
|
||||
|
||||
/* comparison operators .. will throw if the two objects have different
|
||||
* flag settings (which is assumed to indicate that they differ in some
|
||||
@ -118,8 +118,8 @@ class alignas(16) int62_t {
|
||||
* the semantics are well defined and the computation cost is trivial
|
||||
*/
|
||||
|
||||
bool operator!= (int62_t const & other) const { const int64_t vv = v.load(); if (flagged (vv) != other.flagged()) return true; return int62 (vv) != other.val(); }
|
||||
bool operator== (int62_t const & other) const { const int64_t vv = v.load(); if (flagged (vv) != other.flagged()) return false; return int62 (vv) == other.val(); }
|
||||
bool operator!= (int62_t const & other) const { const int64_t vv = v.load(std::memory_order_acquire); if (flagged (vv) != other.flagged()) return true; return int62 (vv) != other.val(); }
|
||||
bool operator== (int62_t const & other) const { const int64_t vv = v.load(std::memory_order_acquire); if (flagged (vv) != other.flagged()) return false; return int62 (vv) == other.val(); }
|
||||
|
||||
explicit operator int64_t() const { return int62(v); }
|
||||
|
||||
@ -133,103 +133,83 @@ class alignas(16) int62_t {
|
||||
int62_t abs() const { const int64_t tmp = v; return int62_t (flagged(tmp), ::llabs(int62(tmp))); }
|
||||
|
||||
int62_t& operator+= (int64_t n) {
|
||||
while (1) {
|
||||
int64_t oldval = v.load (std::memory_order_relaxed);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) + n);
|
||||
if (v.compare_exchange_weak (oldval, newval)) {
|
||||
break;
|
||||
}
|
||||
int64_t oldval = v.load (std::memory_order_acquire);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) + n);
|
||||
while (!v.compare_exchange_weak (oldval, newval, std::memory_order_release, std::memory_order_relaxed)) {
|
||||
newval = build (flagged (oldval), int62 (oldval) + n);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
int62_t& operator-= (int64_t n) {
|
||||
while (1) {
|
||||
int64_t oldval = v.load (std::memory_order_relaxed);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) - n);
|
||||
if (v.compare_exchange_weak (oldval, newval)) {
|
||||
break;
|
||||
}
|
||||
int64_t oldval = v.load (std::memory_order_acquire);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) - n);
|
||||
while (!v.compare_exchange_weak (oldval, newval, std::memory_order_release, std::memory_order_relaxed)) {
|
||||
newval = build (flagged (oldval), int62 (oldval) - n);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
int62_t& operator*= (int64_t n) {
|
||||
while (1) {
|
||||
int64_t oldval = v.load (std::memory_order_relaxed);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) * n);
|
||||
if (v.compare_exchange_weak (oldval, newval)) {
|
||||
break;
|
||||
}
|
||||
int64_t oldval = v.load (std::memory_order_acquire);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) * n);
|
||||
while (!v.compare_exchange_weak (oldval, newval, std::memory_order_release, std::memory_order_relaxed)) {
|
||||
newval = build (flagged (oldval), int62 (oldval) * n);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
int62_t& operator/= (int64_t n) {
|
||||
while (1) {
|
||||
int64_t oldval = v.load (std::memory_order_relaxed);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) / n);
|
||||
if (v.compare_exchange_weak (oldval, newval)) {
|
||||
break;
|
||||
}
|
||||
int64_t oldval = v.load (std::memory_order_acquire);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) / n);
|
||||
while (!v.compare_exchange_weak (oldval, newval, std::memory_order_release, std::memory_order_relaxed)) {
|
||||
newval = build (flagged (oldval), int62 (oldval) / n);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
int62_t& operator%= (int64_t n) {
|
||||
while (1) {
|
||||
int64_t oldval = v.load (std::memory_order_relaxed);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) % n);
|
||||
if (v.compare_exchange_weak (oldval, newval)) {
|
||||
break;
|
||||
}
|
||||
int64_t oldval = v.load (std::memory_order_acquire);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) % n);
|
||||
while (!v.compare_exchange_weak (oldval, newval, std::memory_order_release, std::memory_order_relaxed)) {
|
||||
newval = build (flagged (oldval), int62 (oldval) % n);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
int62_t& operator+= (int62_t n) {
|
||||
while (1) {
|
||||
int64_t oldval = v.load (std::memory_order_relaxed);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) + n.val());
|
||||
if (v.compare_exchange_weak (oldval, newval)) {
|
||||
break;
|
||||
}
|
||||
int64_t oldval = v.load (std::memory_order_acquire);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) + n.val());
|
||||
while (!v.compare_exchange_weak (oldval, newval, std::memory_order_release, std::memory_order_relaxed)) {
|
||||
newval = build (flagged (oldval), int62 (oldval) + n.val());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
int62_t& operator-= (int62_t n) {
|
||||
while (1) {
|
||||
int64_t oldval = v.load (std::memory_order_relaxed);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) - n.val());
|
||||
if (v.compare_exchange_weak (oldval, newval)) {
|
||||
break;
|
||||
}
|
||||
int64_t oldval = v.load (std::memory_order_acquire);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) - n.val());
|
||||
while (!v.compare_exchange_weak (oldval, newval, std::memory_order_release, std::memory_order_relaxed)) {
|
||||
newval = build (flagged (oldval), int62 (oldval) - n.val());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
int62_t& operator*= (int62_t n) {
|
||||
while (1) {
|
||||
int64_t oldval = v.load (std::memory_order_relaxed);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) * n.val());
|
||||
if (v.compare_exchange_weak (oldval, newval)) {
|
||||
break;
|
||||
}
|
||||
int64_t oldval = v.load (std::memory_order_acquire);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) * n.val());
|
||||
while (!v.compare_exchange_weak (oldval, newval, std::memory_order_release, std::memory_order_relaxed)) {
|
||||
newval = build (flagged (oldval), int62 (oldval) * n.val());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
int62_t& operator/= (int62_t n) {
|
||||
while (1) {
|
||||
int64_t oldval = v.load (std::memory_order_relaxed);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) / n.val());
|
||||
if (v.compare_exchange_weak (oldval, newval)) {
|
||||
break;
|
||||
}
|
||||
int64_t oldval = v.load (std::memory_order_acquire);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) / n.val());
|
||||
while (!v.compare_exchange_weak (oldval, newval, std::memory_order_release, std::memory_order_relaxed)) {
|
||||
newval = build (flagged (oldval), int62 (oldval) / n.val());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
int62_t& operator%= (int62_t n) {
|
||||
while (1) {
|
||||
int64_t oldval = v.load (std::memory_order_relaxed);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) % n.val());
|
||||
if (v.compare_exchange_weak (oldval, newval)) {
|
||||
break;
|
||||
}
|
||||
int64_t oldval = v.load (std::memory_order_acquire);
|
||||
int64_t newval = build (flagged (oldval), int62 (oldval) % n.val());
|
||||
while (!v.compare_exchange_weak (oldval, newval, std::memory_order_release, std::memory_order_relaxed)) {
|
||||
newval = build (flagged (oldval), int62 (oldval) % n.val());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user