Commit bb63788b by Martijn Vels Committed by Copybara-Service

Add tracing annotations to absl::Notification

PiperOrigin-RevId: 656188416
Change-Id: I43d901d99f8a4688406b8aab08bc2655a065af46
parent e342b7fc
......@@ -22,7 +22,7 @@ ABSL_NAMESPACE_BEGIN
namespace base_internal {
// Well known Abseil object types that have causality.
enum class ObjectKind { kUnknown, kBlockingCounter };
enum class ObjectKind { kUnknown, kBlockingCounter, kNotification };
// `TraceWait` and `TraceContinue` record the start and end of a potentially
// blocking wait operation on `object`. `object` typically represents a higher
......
......@@ -324,6 +324,9 @@ cc_test(
tags = ["no_test_lexan"],
deps = [
":synchronization",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:tracing_internal",
"//absl/time",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
......
......@@ -112,6 +112,7 @@ absl_cc_library(
absl::raw_logging_internal
absl::stacktrace
absl::symbolize
absl::tracing_internal
absl::time
absl::tracing_internal
Threads::Threads
......@@ -217,8 +218,12 @@ absl_cc_test(
COPTS
${ABSL_TEST_COPTS}
DEPS
absl::base
absl::config
absl::core_headers
absl::synchronization
absl::time
absl::tracing_internal
GTest::gmock_main
)
......
......@@ -17,6 +17,7 @@
#include <atomic>
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/tracing.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
......@@ -24,6 +25,7 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
void Notification::Notify() {
base_internal::TraceSignal(this, TraceObjectKind());
MutexLock l(&this->mutex_);
#ifndef NDEBUG
......@@ -45,31 +47,37 @@ Notification::~Notification() {
}
void Notification::WaitForNotification() const {
base_internal::TraceWait(this, TraceObjectKind());
if (!HasBeenNotifiedInternal(&this->notified_yet_)) {
this->mutex_.LockWhen(Condition(&HasBeenNotifiedInternal,
&this->notified_yet_));
this->mutex_.LockWhen(
Condition(&HasBeenNotifiedInternal, &this->notified_yet_));
this->mutex_.Unlock();
}
base_internal::TraceContinue(this, TraceObjectKind());
}
bool Notification::WaitForNotificationWithTimeout(
absl::Duration timeout) const {
base_internal::TraceWait(this, TraceObjectKind());
bool notified = HasBeenNotifiedInternal(&this->notified_yet_);
if (!notified) {
notified = this->mutex_.LockWhenWithTimeout(
Condition(&HasBeenNotifiedInternal, &this->notified_yet_), timeout);
this->mutex_.Unlock();
}
base_internal::TraceContinue(notified ? this : nullptr, TraceObjectKind());
return notified;
}
bool Notification::WaitForNotificationWithDeadline(absl::Time deadline) const {
base_internal::TraceWait(this, TraceObjectKind());
bool notified = HasBeenNotifiedInternal(&this->notified_yet_);
if (!notified) {
notified = this->mutex_.LockWhenWithDeadline(
Condition(&HasBeenNotifiedInternal, &this->notified_yet_), deadline);
this->mutex_.Unlock();
}
base_internal::TraceContinue(notified ? this : nullptr, TraceObjectKind());
return notified;
}
......
......@@ -53,6 +53,7 @@
#include <atomic>
#include "absl/base/attributes.h"
#include "absl/base/internal/tracing.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
......@@ -75,7 +76,11 @@ class Notification {
//
// Returns the value of the notification's internal "notified" state.
ABSL_MUST_USE_RESULT bool HasBeenNotified() const {
return HasBeenNotifiedInternal(&this->notified_yet_);
if (HasBeenNotifiedInternal(&this->notified_yet_)) {
base_internal::TraceObserved(this, TraceObjectKind());
return true;
}
return false;
}
// Notification::WaitForNotification()
......@@ -108,6 +113,11 @@ class Notification {
void Notify();
private:
// Convenience helper to reduce verbosity at call sites.
static inline constexpr base_internal::ObjectKind TraceObjectKind() {
return base_internal::ObjectKind::kNotification;
}
static inline bool HasBeenNotifiedInternal(
const std::atomic<bool>* notified_yet) {
return notified_yet->load(std::memory_order_acquire);
......
......@@ -15,10 +15,15 @@
#include "absl/synchronization/notification.h"
#include <thread> // NOLINT(build/c++11)
#include <tuple>
#include <vector>
#include "gtest/gtest.h"
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/tracing.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
......@@ -129,5 +134,93 @@ TEST(NotificationTest, SanityTest) {
BasicTests(true, &local_notification2);
}
#if ABSL_HAVE_ATTRIBUTE_WEAK
namespace base_internal {
namespace {
using TraceRecord = std::tuple<const void*, ObjectKind>;
thread_local TraceRecord tls_signal;
thread_local TraceRecord tls_wait;
thread_local TraceRecord tls_continue;
thread_local TraceRecord tls_observed;
} // namespace
// Strong extern "C" implementation.
extern "C" {
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,
ObjectKind kind) {
tls_wait = {object, kind};
}
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,
ObjectKind kind) {
tls_continue = {object, kind};
}
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,
ObjectKind kind) {
tls_signal = {object, kind};
}
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(const void* object,
ObjectKind kind) {
tls_observed = {object, kind};
}
} // extern "C"
TEST(NotificationTest, TracesNotify) {
Notification n;
tls_signal = {};
n.Notify();
EXPECT_EQ(tls_signal, TraceRecord(&n, ObjectKind::kNotification));
}
TEST(NotificationTest, TracesWaitForNotification) {
Notification n;
n.Notify();
tls_wait = tls_continue = {};
n.WaitForNotification();
EXPECT_EQ(tls_wait, TraceRecord(&n, ObjectKind::kNotification));
EXPECT_EQ(tls_continue, TraceRecord(&n, ObjectKind::kNotification));
}
TEST(NotificationTest, TracesWaitForNotificationWithTimeout) {
Notification n;
tls_wait = tls_continue = {};
n.WaitForNotificationWithTimeout(absl::Milliseconds(1));
EXPECT_EQ(tls_wait, TraceRecord(&n, ObjectKind::kNotification));
EXPECT_EQ(tls_continue, TraceRecord(nullptr, ObjectKind::kNotification));
n.Notify();
tls_wait = tls_continue = {};
n.WaitForNotificationWithTimeout(absl::Milliseconds(1));
EXPECT_EQ(tls_wait, TraceRecord(&n, ObjectKind::kNotification));
EXPECT_EQ(tls_continue, TraceRecord(&n, ObjectKind::kNotification));
}
TEST(NotificationTest, TracesHasBeenNotified) {
Notification n;
tls_observed = {};
ASSERT_FALSE(n.HasBeenNotified());
EXPECT_EQ(tls_observed, TraceRecord(nullptr, ObjectKind::kUnknown));
n.Notify();
tls_observed = {};
ASSERT_TRUE(n.HasBeenNotified());
EXPECT_EQ(tls_observed, TraceRecord(&n, ObjectKind::kNotification));
}
} // namespace base_internal
#endif // ABSL_HAVE_ATTRIBUTE_WEAK
ABSL_NAMESPACE_END
} // namespace absl
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment