Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions gloop/perftools/tracing/sync_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -170,17 +170,12 @@ SyncContext::Impl* SyncContext::Impl::RemoveListenerFromCurrent(
auto [new_listener, success] = active_listener->Extract(listener);
if (!PERFTOOLS_VERIFY(success)) return this;

// Signal end of sync session. This is the last event delivered
// where the listener is reachable through the active listener.
// Signal end of sync session and release listener.
listener->OnTraceEndSync(active_sync_id_);

// Set the new listener minus the extracted one and release the listener.
// We guarantee the removed listener can no longer be reached / invoked
// from a call the `ReleaseEventListener()`.
internal::set_active_event_listener(new_listener);
listener->ReleaseEventListener();

// Check if we have remaining listeners. If so, we are still "alive".
// Set the new listener and check if we have remaining listeners.
internal::set_active_event_listener(new_listener);
if (new_listener != nullptr) return this;

// All listeners are removed, delete ourselves.
Expand Down
5 changes: 0 additions & 5 deletions gloop/perftools/tracing/sync_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,11 +251,6 @@ class ABSL_ATTRIBUTE_TRIVIAL_ABI SyncContext {
// This function is a no-op if `listener` is null.
// If `listener` is not present in this instance, then this function will
// check fail in debug builds, and release the listener in production builds.
// Any call to `ReleaseEventListener()` on the provided `listener` or any
// embedded (multiplexed) listeners inside `listeners` is guaranteed to
// occur _after_ the current active listener for the instance has been
// updated. I.e.: The listener is no longer invoked from traced calls from
// non trivial code executed by any listener specific release logic.
void RemoveListenerFromCurrent(Access, TraceEventListener* listener);

// Returns `true` if the provided listener is present in this instance.
Expand Down
29 changes: 5 additions & 24 deletions gloop/perftools/tracing/sync_context_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -529,34 +529,15 @@ TEST_F(SyncContextTest, RemoveListenersFromCurrent) {
EXPECT_CALL(mock1, OnTraceBeginSync(kMainSyncId, _));
EXPECT_CALL(mock2, OnTraceBeginSync(kMainSyncId, _));
WithContext with(std::move(root));
TraceEventListener* active_listener = internal::active_event_listener();

// EndSync() is the last sync event invoked.
EXPECT_CALL(mock2, OnTraceEndSync(kMainSyncId)).WillOnce([&](auto) {
EXPECT_THAT(internal::active_event_listener(), Eq(active_listener));
});
// Extract() is the final interaction where active listener is in place.
EXPECT_CALL(mock2, Extract(&mock2)).WillOnce([&](auto...) {
EXPECT_THAT(internal::active_event_listener(), Eq(active_listener));
return std::pair<TraceEventListener*, bool>(nullptr, true);
});
// Release() is guaranteed to be invoked after the active listener is reset.
EXPECT_CALL(mock2, ReleaseEventListener()).WillOnce([&](auto...) {
EXPECT_THAT(internal::active_event_listener(), Eq(&mock1));
});
EXPECT_CALL(mock2, OnTraceEndSync(kMainSyncId));
EXPECT_CALL(mock2, Extract(&mock2));
EXPECT_CALL(mock2, ReleaseEventListener());
Context::RemoveListenerFromCurrent(&mock2);

// EndSync() is the last sync event invoked.
EXPECT_CALL(mock1, OnTraceEndSync(kMainSyncId));
// Extract() is the final interaction where active listener is in place.
EXPECT_CALL(mock1, Extract(&mock1)).WillOnce([&](auto...) {
EXPECT_THAT(internal::active_event_listener(), Eq(&mock1));
return std::pair<TraceEventListener*, bool>(nullptr, true);
});
// Release() is guaranteed to be invoked after the active listener is reset.
EXPECT_CALL(mock1, ReleaseEventListener()).WillOnce([&](auto...) {
EXPECT_THAT(internal::active_event_listener(), Eq(nullptr));
});
EXPECT_CALL(mock1, Extract(&mock1));
EXPECT_CALL(mock1, ReleaseEventListener());
Context::RemoveListenerFromCurrent(&mock1);
}

Expand Down
Loading