summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authornduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-20 06:35:15 +0000
committernduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-20 06:35:15 +0000
commit9f89a3f2fdbf787fb689e5edf3be6ae6f0eb406f (patch)
tree075aeb72f516be48a3de74d2bc2d5af33f960a21 /base
parent2fba57366ad51980bfd54aaddc7755529986423f (diff)
downloadchromium_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.cc35
-rw-r--r--base/debug/trace_event_impl.h22
-rw-r--r--base/debug/trace_event_unittest.cc80
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();