absl: remove special handling of Condition::kTrue
Condition::kTrue is used very rarely (frequently its uses even indicate
confusion and bugs). But we pay few additional branches for kTrue
on all Condition operations.
Remove that special handling and simplify logic.
PiperOrigin-RevId: 563691160
Change-Id: I76125adde4872489da069dd9c894ed73a65d1d83
diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc
index 353a828..9a25570 100644
--- a/absl/synchronization/mutex.cc
+++ b/absl/synchronization/mutex.cc
@@ -966,8 +966,7 @@
} while (s->priority <= advance_to->priority);
// termination guaranteed because s->priority > head->priority
// and head is the end of a skip chain
- } else if (waitp->how == kExclusive &&
- Condition::GuaranteedEqual(waitp->cond, nullptr)) {
+ } else if (waitp->how == kExclusive && waitp->cond == nullptr) {
// An unlocker could be scanning the queue, but we know it will recheck
// the queue front for writers that have no condition, which is what s
// is, so an insert at front is safe.
@@ -1627,15 +1626,11 @@
SynchWaitParams waitp(how, &cond, t, nullptr /*no cvmu*/,
Synch_GetPerThreadAnnotated(this),
nullptr /*no cv_word*/);
- int flags = kMuHasBlocked;
- if (!Condition::GuaranteedEqual(&cond, nullptr)) {
- flags |= kMuIsCond;
- }
this->UnlockSlow(&waitp);
this->Block(waitp.thread);
ABSL_TSAN_MUTEX_POST_UNLOCK(this, TsanFlags(how));
ABSL_TSAN_MUTEX_PRE_LOCK(this, TsanFlags(how));
- this->LockSlowLoop(&waitp, flags);
+ this->LockSlowLoop(&waitp, kMuHasBlocked | kMuIsCond);
bool res = waitp.cond != nullptr || // => cond known true from LockSlowLoop
EvalConditionAnnotated(&cond, this, true, false, how == kShared);
ABSL_TSAN_MUTEX_POST_LOCK(this, TsanFlags(how), 0);
@@ -1917,7 +1912,7 @@
SynchWaitParams waitp(how, cond, t, nullptr /*no cvmu*/,
Synch_GetPerThreadAnnotated(this),
nullptr /*no cv_word*/);
- if (!Condition::GuaranteedEqual(cond, nullptr)) {
+ if (cond != nullptr) {
flags |= kMuIsCond;
}
if (unlock) {
@@ -2211,7 +2206,7 @@
}
}
if (h->next->waitp->how == kExclusive &&
- Condition::GuaranteedEqual(h->next->waitp->cond, nullptr)) {
+ h->next->waitp->cond == nullptr) {
// easy case: writer with no condition; no need to search
pw = h; // wake w, the successor of h (=pw)
w = h->next;
@@ -2815,17 +2810,11 @@
StoreCallback(dereference);
}
-bool Condition::Eval() const {
- // eval_ == null for kTrue
- return (this->eval_ == nullptr) || (*this->eval_)(this);
-}
+bool Condition::Eval() const { return (*this->eval_)(this); }
bool Condition::GuaranteedEqual(const Condition* a, const Condition* b) {
- // kTrue logic.
- if (a == nullptr || a->eval_ == nullptr) {
- return b == nullptr || b->eval_ == nullptr;
- } else if (b == nullptr || b->eval_ == nullptr) {
- return false;
+ if (a == nullptr || b == nullptr) {
+ return a == nullptr && b == nullptr;
}
// Check equality of the representative fields.
return a->eval_ == b->eval_ && a->arg_ == b->arg_ &&
diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h
index 645c26d..f2bafa9 100644
--- a/absl/synchronization/mutex.h
+++ b/absl/synchronization/mutex.h
@@ -807,10 +807,10 @@
#endif
// Function with which to evaluate callbacks and/or arguments.
- bool (*eval_)(const Condition*) = nullptr;
+ bool (*const eval_)(const Condition*);
// Either an argument for a function call or an object for a method call.
- void* arg_ = nullptr;
+ void* const arg_;
// Various functions eval_ can point to:
static bool CallVoidPtrFunction(const Condition*);
@@ -833,8 +833,10 @@
std::memcpy(callback, callback_, sizeof(*callback));
}
+ static bool AlwaysTrue(const Condition*) { return true; }
+
// Used only to create kTrue.
- constexpr Condition() = default;
+ constexpr Condition() : eval_(AlwaysTrue), arg_(nullptr) {}
};
// -----------------------------------------------------------------------------