diff options
author | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-13 17:44:56 +0000 |
---|---|---|
committer | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-13 17:44:56 +0000 |
commit | df57e909b09e4264ceede6d3b01c390c5c33f736 (patch) | |
tree | 1eaa5ec03957da78df78ba3460d572ee1196fedf /base/debug/trace_event_impl.cc | |
parent | 0d66d7eebad21850083e3a11b1fcaaeb2a4d67ce (diff) | |
download | chromium_src-df57e909b09e4264ceede6d3b01c390c5c33f736.zip chromium_src-df57e909b09e4264ceede6d3b01c390c5c33f736.tar.gz chromium_src-df57e909b09e4264ceede6d3b01c390c5c33f736.tar.bz2 |
Notify TraceLog observers outside of the lock
This allows observers to call code that uses TRACE_EVENT macros.
BUG=none, noticed while developing memory tracing patch
TEST=Added to base_unittests TraceEventTestFixture
Review URL: https://chromiumcodereview.appspot.com/16829002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@206109 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/debug/trace_event_impl.cc')
-rw-r--r-- | base/debug/trace_event_impl.cc | 185 |
1 files changed, 106 insertions, 79 deletions
diff --git a/base/debug/trace_event_impl.cc b/base/debug/trace_event_impl.cc index ab282e7..176f67c 100644 --- a/base/debug/trace_event_impl.cc +++ b/base/debug/trace_event_impl.cc @@ -910,62 +910,71 @@ void TraceLog::GetKnownCategoryGroups( void TraceLog::SetEnabled(const CategoryFilter& category_filter, Options options) { - AutoLock lock(lock_); + std::vector<EnabledStateObserver*> observer_list; + { + AutoLock lock(lock_); - if (enable_count_++ > 0) { - if (options != trace_options_) { - DLOG(ERROR) << "Attemting to re-enable tracing with a different " - << "set of options."; + if (enable_count_++ > 0) { + if (options != trace_options_) { + DLOG(ERROR) << "Attemting to re-enable tracing with a different " + << "set of options."; + } + + category_filter_.Merge(category_filter); + EnableIncludedCategoryGroups(); + return; } - category_filter_.Merge(category_filter); - EnableIncludedCategoryGroups(); - return; - } + if (options != trace_options_) { + trace_options_ = options; + logged_events_.reset(GetTraceBuffer()); + } - if (options != trace_options_) { - trace_options_ = options; - logged_events_.reset(GetTraceBuffer()); - } + if (dispatching_to_observer_list_) { + DLOG(ERROR) << + "Cannot manipulate TraceLog::Enabled state from an observer."; + return; + } - if (dispatching_to_observer_list_) { - DLOG(ERROR) << - "Cannot manipulate TraceLog::Enabled state from an observer."; - return; - } + num_traces_recorded_++; - num_traces_recorded_++; + category_filter_ = CategoryFilter(category_filter); + EnableIncludedCategoryGroups(); - dispatching_to_observer_list_ = true; - FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, - OnTraceLogWillEnable()); - dispatching_to_observer_list_ = false; + // Not supported in split-dll build. http://crbug.com/237249 + #if !defined(CHROME_SPLIT_DLL) + if (options & ENABLE_SAMPLING) { + sampling_thread_.reset(new TraceSamplingThread); + sampling_thread_->RegisterSampleBucket( + &g_trace_state0, + "bucket0", + Bind(&TraceSamplingThread::DefaultSampleCallback)); + sampling_thread_->RegisterSampleBucket( + &g_trace_state1, + "bucket1", + Bind(&TraceSamplingThread::DefaultSampleCallback)); + sampling_thread_->RegisterSampleBucket( + &g_trace_state2, + "bucket2", + Bind(&TraceSamplingThread::DefaultSampleCallback)); + if (!PlatformThread::Create( + 0, sampling_thread_.get(), &sampling_thread_handle_)) { + DCHECK(false) << "failed to create thread"; + } + } + #endif - category_filter_ = CategoryFilter(category_filter); - EnableIncludedCategoryGroups(); + dispatching_to_observer_list_ = true; + observer_list = enabled_state_observer_list_; + } + // Notify observers outside the lock in case they trigger trace events. + for (size_t i = 0; i < observer_list.size(); ++i) + observer_list[i]->OnTraceLogEnabled(); - // Not supported in split-dll build. http://crbug.com/237249 -#if !defined(CHROME_SPLIT_DLL) - if (options & ENABLE_SAMPLING) { - sampling_thread_.reset(new TraceSamplingThread); - sampling_thread_->RegisterSampleBucket( - &g_trace_state0, - "bucket0", - Bind(&TraceSamplingThread::DefaultSampleCallback)); - sampling_thread_->RegisterSampleBucket( - &g_trace_state1, - "bucket1", - Bind(&TraceSamplingThread::DefaultSampleCallback)); - sampling_thread_->RegisterSampleBucket( - &g_trace_state2, - "bucket2", - Bind(&TraceSamplingThread::DefaultSampleCallback)); - if (!PlatformThread::Create( - 0, sampling_thread_.get(), &sampling_thread_handle_)) { - DCHECK(false) << "failed to create thread"; - } + { + AutoLock lock(lock_); + dispatching_to_observer_list_ = false; } -#endif } const CategoryFilter& TraceLog::GetCurrentCategoryFilter() { @@ -975,39 +984,49 @@ const CategoryFilter& TraceLog::GetCurrentCategoryFilter() { } void TraceLog::SetDisabled() { - AutoLock lock(lock_); - DCHECK(enable_count_ > 0); - if (--enable_count_ != 0) - return; + std::vector<EnabledStateObserver*> observer_list; + { + AutoLock lock(lock_); + DCHECK(enable_count_ > 0); + if (--enable_count_ != 0) + return; - if (dispatching_to_observer_list_) { - DLOG(ERROR) - << "Cannot manipulate TraceLog::Enabled state from an observer."; - return; - } + if (dispatching_to_observer_list_) { + DLOG(ERROR) + << "Cannot manipulate TraceLog::Enabled state from an observer."; + return; + } - if (sampling_thread_.get()) { - // Stop the sampling thread. - sampling_thread_->Stop(); - lock_.Release(); - PlatformThread::Join(sampling_thread_handle_); - lock_.Acquire(); - sampling_thread_handle_ = PlatformThreadHandle(); - sampling_thread_.reset(); + if (sampling_thread_.get()) { + // Stop the sampling thread. + sampling_thread_->Stop(); + lock_.Release(); + PlatformThread::Join(sampling_thread_handle_); + lock_.Acquire(); + sampling_thread_handle_ = PlatformThreadHandle(); + sampling_thread_.reset(); + } + + category_filter_.Clear(); + watch_category_ = NULL; + watch_event_name_ = ""; + for (int i = 0; i < g_category_index; i++) + SetCategoryGroupEnabled(i, false); + AddThreadNameMetadataEvents(); + + dispatching_to_observer_list_ = true; + observer_list = enabled_state_observer_list_; } - dispatching_to_observer_list_ = true; - FOR_EACH_OBSERVER(EnabledStateChangedObserver, - enabled_state_observer_list_, - OnTraceLogWillDisable()); - dispatching_to_observer_list_ = false; + // Dispatch to observers outside the lock in case the observer triggers a + // trace event. + for (size_t i = 0; i < observer_list.size(); ++i) + observer_list[i]->OnTraceLogDisabled(); - category_filter_.Clear(); - watch_category_ = NULL; - watch_event_name_ = ""; - for (int i = 0; i < g_category_index; i++) - SetCategoryGroupEnabled(i, false); - AddThreadNameMetadataEvents(); + { + AutoLock lock(lock_); + dispatching_to_observer_list_ = false; + } } int TraceLog::GetNumTracesRecorded() { @@ -1017,13 +1036,17 @@ int TraceLog::GetNumTracesRecorded() { return num_traces_recorded_; } -void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { - enabled_state_observer_list_.AddObserver(listener); +void TraceLog::AddEnabledStateObserver(EnabledStateObserver* listener) { + enabled_state_observer_list_.push_back(listener); } -void TraceLog::RemoveEnabledStateObserver( - EnabledStateChangedObserver* listener) { - enabled_state_observer_list_.RemoveObserver(listener); +void TraceLog::RemoveEnabledStateObserver(EnabledStateObserver* listener) { + std::vector<EnabledStateObserver*>::iterator it = + std::find(enabled_state_observer_list_.begin(), + enabled_state_observer_list_.end(), + listener); + if (it != enabled_state_observer_list_.end()) + enabled_state_observer_list_.erase(it); } float TraceLog::GetBufferPercentFull() const { @@ -1320,6 +1343,10 @@ void TraceLog::SetTimeOffset(TimeDelta offset) { time_offset_ = offset; } +size_t TraceLog::GetObserverCountForTest() const { + return enabled_state_observer_list_.size(); +} + bool CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace( const std::string& str) { return str.empty() || |