mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
Add tracing annotations to absl::Notification
PiperOrigin-RevId: 656188416 Change-Id: I43d901d99f8a4688406b8aab08bc2655a065af46
This commit is contained in:
committed by
Copybara-Service
parent
e342b7fc37
commit
bb63788b4b
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user