| Index: base/trace_event/blame_context.cc
|
| diff --git a/base/trace_event/blame_context.cc b/base/trace_event/blame_context.cc
|
| index 27d2d2eb7509c2b57f161aa5263c2787cc337a3c..234c2e7a4f0a00ce7ac0b6b716ce193f4f91c632 100644
|
| --- a/base/trace_event/blame_context.cc
|
| +++ b/base/trace_event/blame_context.cc
|
| @@ -5,6 +5,7 @@
|
| #include "base/trace_event/blame_context.h"
|
|
|
| #include "base/strings/stringprintf.h"
|
| +#include "base/thread_task_runner_handle.h"
|
| #include "base/trace_event/trace_event.h"
|
| #include "base/trace_event/trace_event_argument.h"
|
|
|
| @@ -24,17 +25,18 @@ BlameContext::BlameContext(const char* category,
|
| id_(id),
|
| parent_scope_(parent_context ? parent_context->scope() : nullptr),
|
| parent_id_(parent_context ? parent_context->id() : 0),
|
| - category_group_enabled_(nullptr) {
|
| + category_group_enabled_(nullptr),
|
| + task_runner_(ThreadTaskRunnerHandle::Get()),
|
| + weak_factory_(this) {
|
| DCHECK(!parent_context || !std::strcmp(name_, parent_context->name()))
|
| << "Parent blame context must have the same name";
|
| }
|
|
|
| BlameContext::~BlameContext() {
|
| - DCHECK(WasInitialized());
|
| + UnregisterFromTraceLog();
|
| TRACE_EVENT_API_ADD_TRACE_EVENT(
|
| TRACE_EVENT_PHASE_DELETE_OBJECT, category_group_enabled_, type_, scope_,
|
| id_, 0, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID);
|
| - trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
|
| }
|
|
|
| void BlameContext::Enter() {
|
| @@ -54,6 +56,7 @@ void BlameContext::Leave() {
|
| }
|
|
|
| void BlameContext::TakeSnapshot() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| DCHECK(WasInitialized());
|
| if (!*category_group_enabled_)
|
| return;
|
| @@ -71,9 +74,18 @@ void BlameContext::TakeSnapshot() {
|
| arg_values, TRACE_EVENT_FLAG_HAS_ID);
|
| }
|
|
|
| +// Called by TraceLog from a thread possibly different from the one where this
|
| +// BlameContext instance was constructed. Since any access to TraceLog's list
|
| +// of observers is lock-guarded, we can access members of BlameContext from a
|
| +// different thread via a raw pointer safely without worrying about threading
|
| +// issues or pointer validity.
|
| void BlameContext::OnTraceLogEnabled() {
|
| DCHECK(WasInitialized());
|
| - TakeSnapshot();
|
| + if (task_runner()->BelongsToCurrentThread())
|
| + TakeSnapshot();
|
| + else
|
| + task_runner()->PostTask(FROM_HERE,
|
| + Bind(&BlameContext::TakeSnapshot, get_weak()));
|
| }
|
|
|
| void BlameContext::OnTraceLogDisabled() {}
|
| @@ -94,13 +106,22 @@ void BlameContext::Initialize() {
|
| TRACE_EVENT_API_ADD_TRACE_EVENT(
|
| TRACE_EVENT_PHASE_CREATE_OBJECT, category_group_enabled_, type_, scope_,
|
| id_, 0, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID);
|
| - trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
|
| TakeSnapshot();
|
| + trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
|
| + registered_ = true;
|
| }
|
|
|
| bool BlameContext::WasInitialized() const {
|
| return category_group_enabled_ != nullptr;
|
| }
|
|
|
| +void BlameContext::UnregisterFromTraceLog() {
|
| + DCHECK(WasInitialized());
|
| + if (!registered_)
|
| + return;
|
| + trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
|
| + registered_ = false;
|
| +}
|
| +
|
| } // namespace trace_event
|
| } // namespace base
|
|
|