diff options
author | nduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-20 06:35:15 +0000 |
---|---|---|
committer | nduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-20 06:35:15 +0000 |
commit | 9f89a3f2fdbf787fb689e5edf3be6ae6f0eb406f (patch) | |
tree | 075aeb72f516be48a3de74d2bc2d5af33f960a21 /base | |
parent | 2fba57366ad51980bfd54aaddc7755529986423f (diff) | |
download | chromium_src-9f89a3f2fdbf787fb689e5edf3be6ae6f0eb406f.zip chromium_src-9f89a3f2fdbf787fb689e5edf3be6ae6f0eb406f.tar.gz chromium_src-9f89a3f2fdbf787fb689e5edf3be6ae6f0eb406f.tar.bz2 |
Add EnabledStateObserver to TraceLog as prelude to hooking V8 GC events.
Review URL: http://codereview.chromium.org/9307002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@122730 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/debug/trace_event_impl.cc | 35 | ||||
-rw-r--r-- | base/debug/trace_event_impl.h | 22 | ||||
-rw-r--r-- | base/debug/trace_event_unittest.cc | 80 |
3 files changed, 136 insertions, 1 deletions
diff --git a/base/debug/trace_event_impl.cc b/base/debug/trace_event_impl.cc index 39542f7..b81e32a 100644 --- a/base/debug/trace_event_impl.cc +++ b/base/debug/trace_event_impl.cc @@ -322,7 +322,8 @@ TraceLog* TraceLog::GetInstance() { } TraceLog::TraceLog() - : enabled_(false) { + : enabled_(false) + , dispatching_to_observer_list_(false) { SetProcessID(static_cast<int>(base::GetCurrentProcId())); // Trace is enabled or disabled on one thread while other threads are // accessing the enabled flag. We don't care whether edge-case events are @@ -425,6 +426,18 @@ void TraceLog::SetEnabled(const std::vector<std::string>& included_categories, AutoLock lock(lock_); if (enabled_) return; + + if (dispatching_to_observer_list_) { + DLOG(ERROR) << + "Cannot manipulate TraceLog::Enabled state from an observer."; + return; + } + + dispatching_to_observer_list_ = true; + FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, + OnTraceLogWillEnable()); + dispatching_to_observer_list_ = false; + logged_events_.reserve(1024); enabled_ = true; included_categories_ = included_categories; @@ -474,6 +487,17 @@ void TraceLog::SetDisabled() { if (!enabled_) return; + if (dispatching_to_observer_list_) { + DLOG(ERROR) + << "Cannot manipulate TraceLog::Enabled state from an observer."; + return; + } + + dispatching_to_observer_list_ = true; + FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, + OnTraceLogWillDisable()); + dispatching_to_observer_list_ = false; + enabled_ = false; included_categories_.clear(); excluded_categories_.clear(); @@ -492,6 +516,15 @@ void TraceLog::SetEnabled(bool enabled) { SetDisabled(); } +void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { + enabled_state_observer_list_.AddObserver(listener); +} + +void TraceLog::RemoveEnabledStateObserver( + EnabledStateChangedObserver* listener) { + enabled_state_observer_list_.RemoveObserver(listener); +} + float TraceLog::GetBufferPercentFull() const { return (float)((double)logged_events_.size()/(double)kTraceEventBufferSize); } diff --git a/base/debug/trace_event_impl.h b/base/debug/trace_event_impl.h index 7f7a0cb..1806f893 100644 --- a/base/debug/trace_event_impl.h +++ b/base/debug/trace_event_impl.h @@ -15,6 +15,7 @@ #include "base/callback.h" #include "base/hash_tables.h" #include "base/memory/ref_counted_memory.h" +#include "base/observer_list.h" #include "base/string_util.h" #include "base/synchronization/lock.h" #include "base/timer.h" @@ -194,6 +195,25 @@ class BASE_EXPORT TraceLog { void SetEnabled(bool enabled); bool IsEnabled() { return enabled_; } + // Enabled state listeners give a callback when tracing is enabled or + // disabled. This can be used to tie into other library's tracing systems + // on-demand. + class EnabledStateChangedObserver { + public: + // Called just before the tracing system becomes + // enabled. TraceLog::IsEnabled will return false at this point and trace + // macros and methods called within the observer will deadlock. + virtual void OnTraceLogWillEnable() { } + + // Called just before the tracing system disables. TraceLog::IsEnabled is + // still false at this point TRACE macros will still be capturing + // data. However, trace macros and methods called within the observer will + // deadlock. + virtual void OnTraceLogWillDisable() { } + }; + void AddEnabledStateObserver(EnabledStateChangedObserver* listener); + void RemoveEnabledStateObserver(EnabledStateChangedObserver* listener); + float GetBufferPercentFull() const; // When enough events are collected, they are handed (in bulk) to @@ -286,6 +306,8 @@ class BASE_EXPORT TraceLog { std::vector<TraceEvent> logged_events_; std::vector<std::string> included_categories_; std::vector<std::string> excluded_categories_; + bool dispatching_to_observer_list_; + ObserverList<EnabledStateChangedObserver> enabled_state_observer_list_; base::hash_map<int, std::string> thread_names_; diff --git a/base/debug/trace_event_unittest.cc b/base/debug/trace_event_unittest.cc index b756b9a..9afd68b 100644 --- a/base/debug/trace_event_unittest.cc +++ b/base/debug/trace_event_unittest.cc @@ -62,6 +62,8 @@ class TraceEventTestFixture : public testing::Test { old_thread_name_ = PlatformThread::GetName(); } virtual void TearDown() { + if (TraceLog::GetInstance()) + EXPECT_FALSE(TraceLog::GetInstance()->IsEnabled()); PlatformThread::SetName(old_thread_name_ ? old_thread_name_ : ""); } @@ -625,6 +627,84 @@ TEST_F(TraceEventTestFixture, DataCaptured) { ValidateAllTraceMacrosCreatedData(trace_parsed_); } +class MockEnabledStateChangedObserver : + public base::debug::TraceLog::EnabledStateChangedObserver { + public: + MOCK_METHOD0(OnTraceLogWillEnable, void()); + MOCK_METHOD0(OnTraceLogWillDisable, void()); +}; + +TEST_F(TraceEventTestFixture, EnabledObserverFiresOnEnable) { + ManualTestSetUp(); + + MockEnabledStateChangedObserver observer; + TraceLog::GetInstance()->AddEnabledStateObserver(&observer); + + EXPECT_CALL(observer, OnTraceLogWillEnable()) + .Times(1); + TraceLog::GetInstance()->SetEnabled(true); + testing::Mock::VerifyAndClear(&observer); + + // Cleanup. + TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer); + TraceLog::GetInstance()->SetEnabled(false); +} + +TEST_F(TraceEventTestFixture, EnabledObserverDoesntFireOnSecondEnable) { + ManualTestSetUp(); + + TraceLog::GetInstance()->SetEnabled(true); + + testing::StrictMock<MockEnabledStateChangedObserver> observer; + TraceLog::GetInstance()->AddEnabledStateObserver(&observer); + + EXPECT_CALL(observer, OnTraceLogWillEnable()) + .Times(0); + EXPECT_CALL(observer, OnTraceLogWillDisable()) + .Times(0); + TraceLog::GetInstance()->SetEnabled(true); + testing::Mock::VerifyAndClear(&observer); + + // Cleanup. + TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer); + TraceLog::GetInstance()->SetEnabled(false); +} + +TEST_F(TraceEventTestFixture, EnabledObserverDoesntFireOnUselessDisable) { + ManualTestSetUp(); + + + testing::StrictMock<MockEnabledStateChangedObserver> observer; + TraceLog::GetInstance()->AddEnabledStateObserver(&observer); + + EXPECT_CALL(observer, OnTraceLogWillEnable()) + .Times(0); + EXPECT_CALL(observer, OnTraceLogWillDisable()) + .Times(0); + TraceLog::GetInstance()->SetEnabled(false); + testing::Mock::VerifyAndClear(&observer); + + // Cleanup. + TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer); +} + +TEST_F(TraceEventTestFixture, EnabledObserverFiresOnDisable) { + ManualTestSetUp(); + + TraceLog::GetInstance()->SetEnabled(true); + + MockEnabledStateChangedObserver observer; + TraceLog::GetInstance()->AddEnabledStateObserver(&observer); + + EXPECT_CALL(observer, OnTraceLogWillDisable()) + .Times(1); + TraceLog::GetInstance()->SetEnabled(false); + testing::Mock::VerifyAndClear(&observer); + + // Cleanup. + TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer); +} + // Test that categories work. TEST_F(TraceEventTestFixture, Categories) { ManualTestSetUp(); |