Chromium Code Reviews| Index: base/debug/trace_event_synthetic_delay.cc |
| diff --git a/base/debug/trace_event_synthetic_delay.cc b/base/debug/trace_event_synthetic_delay.cc |
| index cb9904621f6082cb944eb3a7e38a957a92073f46..5d7444ae319eadbfdbede0e8f76d326b96baeef9 100644 |
| --- a/base/debug/trace_event_synthetic_delay.cc |
| +++ b/base/debug/trace_event_synthetic_delay.cc |
| @@ -4,8 +4,6 @@ |
| #include "base/debug/trace_event_synthetic_delay.h" |
| #include "base/memory/singleton.h" |
| -#include "base/threading/platform_thread.h" |
| -#include "base/threading/thread_local.h" |
| namespace { |
| const int kMaxSyntheticDelays = 32; |
| @@ -17,24 +15,11 @@ namespace debug { |
| TraceEventSyntheticDelayClock::TraceEventSyntheticDelayClock() {} |
| TraceEventSyntheticDelayClock::~TraceEventSyntheticDelayClock() {} |
| -// Thread-local state for each synthetic delay point. This allows the same delay |
| -// to be applied to multiple threads simultaneously. |
| -struct ThreadState { |
| - ThreadState(); |
| - |
| - base::TimeTicks start_time; |
| - unsigned trigger_count; |
| - int generation; |
| -}; |
| - |
| -ThreadState::ThreadState() : trigger_count(0u), generation(0) {} |
| - |
| class TraceEventSyntheticDelayRegistry : public TraceEventSyntheticDelayClock { |
| public: |
| static TraceEventSyntheticDelayRegistry* GetInstance(); |
| TraceEventSyntheticDelay* GetOrCreateDelay(const char* name); |
| - ThreadState* GetThreadState(int index); |
| void ResetAllDelays(); |
| // TraceEventSyntheticDelayClock implementation. |
| @@ -50,13 +35,11 @@ class TraceEventSyntheticDelayRegistry : public TraceEventSyntheticDelayClock { |
| TraceEventSyntheticDelay dummy_delay_; |
| base::subtle::Atomic32 delay_count_; |
| - ThreadLocalPointer<ThreadState> thread_states_; |
| - |
| DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelayRegistry); |
| }; |
| TraceEventSyntheticDelay::TraceEventSyntheticDelay() |
| - : mode_(STATIC), generation_(0), thread_state_index_(0), clock_(NULL) {} |
| + : mode_(STATIC), begin_count_(0), trigger_count_(0), clock_(NULL) {} |
| TraceEventSyntheticDelay::~TraceEventSyntheticDelay() {} |
| @@ -68,33 +51,30 @@ TraceEventSyntheticDelay* TraceEventSyntheticDelay::Lookup( |
| void TraceEventSyntheticDelay::Initialize( |
| const std::string& name, |
| - TraceEventSyntheticDelayClock* clock, |
| - int thread_state_index) { |
| + TraceEventSyntheticDelayClock* clock) { |
| name_ = name; |
| clock_ = clock; |
| - thread_state_index_ = thread_state_index; |
| } |
| void TraceEventSyntheticDelay::SetTargetDuration( |
| base::TimeDelta target_duration) { |
| AutoLock lock(lock_); |
| target_duration_ = target_duration; |
| - generation_++; |
| + trigger_count_ = 0; |
| + begin_count_ = 0; |
| } |
| void TraceEventSyntheticDelay::SetMode(Mode mode) { |
| AutoLock lock(lock_); |
| mode_ = mode; |
| - generation_++; |
| } |
| void TraceEventSyntheticDelay::SetClock(TraceEventSyntheticDelayClock* clock) { |
| AutoLock lock(lock_); |
| clock_ = clock; |
| - generation_++; |
| } |
| -void TraceEventSyntheticDelay::Activate() { |
| +void TraceEventSyntheticDelay::Begin() { |
| // Note that we check for a non-zero target duration without locking to keep |
| // things quick for the common case when delays are disabled. Since the delay |
| // calculation is done with a lock held, it will always be correct. The only |
| @@ -104,47 +84,52 @@ void TraceEventSyntheticDelay::Activate() { |
| if (!target_duration_.ToInternalValue()) |
| return; |
| - ThreadState* thread_state = |
| - TraceEventSyntheticDelayRegistry::GetInstance()-> |
| - GetThreadState(thread_state_index_); |
| - if (!thread_state->start_time.ToInternalValue()) |
| - thread_state->start_time = clock_->Now(); |
| + BeginInternal(1, false); |
| } |
| -void TraceEventSyntheticDelay::Apply() { |
| +void TraceEventSyntheticDelay::BeginInternal(int begin_delta, bool reset) { |
|
brianderson
2013/12/10 02:25:39
When reset is true, is it possible that there is a
|
| + AutoLock lock(lock_); |
| + if (reset) |
| + begin_count_ = begin_delta; |
| + else |
| + begin_count_ += begin_delta; |
| + |
| + if (!reset && begin_count_ - begin_delta > 0) |
| + return; |
| + start_time_ = clock_->Now(); |
| +} |
| + |
| +void TraceEventSyntheticDelay::End() { |
| ANNOTATE_BENIGN_RACE(&target_duration_, "Synthetic delay duration"); |
| if (!target_duration_.ToInternalValue()) |
| return; |
| - ThreadState* thread_state = |
| - TraceEventSyntheticDelayRegistry::GetInstance()-> |
| - GetThreadState(thread_state_index_); |
| - if (!thread_state->start_time.ToInternalValue()) |
| - return; |
| - base::TimeTicks now = clock_->Now(); |
| - base::TimeTicks start_time = thread_state->start_time; |
| base::TimeTicks end_time; |
| - thread_state->start_time = base::TimeTicks(); |
| - |
| { |
| AutoLock lock(lock_); |
| - if (thread_state->generation != generation_) { |
| - thread_state->trigger_count = 0; |
| - thread_state->generation = generation_; |
| - } |
| + if (!begin_count_ || --begin_count_ > 0) |
| + return; |
| + base::TimeTicks now = clock_->Now(); |
| - if (mode_ == ONE_SHOT && thread_state->trigger_count++) |
| + if (mode_ == ONE_SHOT && trigger_count_++) |
| return; |
| - else if (mode_ == ALTERNATING && thread_state->trigger_count++ % 2) |
| + else if (mode_ == ALTERNATING && trigger_count_++ % 2) |
| return; |
| - end_time = start_time + target_duration_; |
| + end_time = start_time_ + target_duration_; |
| if (now >= end_time) |
| return; |
| } |
| ApplyDelay(end_time); |
| } |
| +void TraceEventSyntheticDelay::ResetAndBeginMultiple(int begin_count) { |
| + ANNOTATE_BENIGN_RACE(&target_duration_, "Synthetic delay duration"); |
| + if (!target_duration_.ToInternalValue()) |
| + return; |
| + BeginInternal(begin_count, true); |
| +} |
| + |
| void TraceEventSyntheticDelay::ApplyDelay(base::TimeTicks end_time) { |
| TRACE_EVENT0("synthetic_delay", name_.c_str()); |
| while (clock_->Now() < end_time) { |
| @@ -184,24 +169,11 @@ TraceEventSyntheticDelay* TraceEventSyntheticDelayRegistry::GetOrCreateDelay( |
| if (delay_count >= kMaxSyntheticDelays) |
| return &dummy_delay_; |
| - delays_[delay_count].Initialize(std::string(name), this, delay_count); |
| + delays_[delay_count].Initialize(std::string(name), this); |
| base::subtle::Release_Store(&delay_count_, delay_count + 1); |
| return &delays_[delay_count]; |
| } |
| -ThreadState* TraceEventSyntheticDelayRegistry::GetThreadState(int index) { |
| - DCHECK(index >= 0 && index < kMaxSyntheticDelays); |
| - if (index < 0 || index >= kMaxSyntheticDelays) |
| - return NULL; |
| - |
| - // Note that these thread states are leaked at program exit. They will only |
| - // get allocated if synthetic delays are actually used. |
| - ThreadState* thread_states = thread_states_.Get(); |
| - if (!thread_states) |
| - thread_states_.Set((thread_states = new ThreadState[kMaxSyntheticDelays])); |
| - return &thread_states[index]; |
| -} |
| - |
| base::TimeTicks TraceEventSyntheticDelayRegistry::Now() { |
| return base::TimeTicks::HighResNow(); |
| } |
| @@ -225,10 +197,10 @@ namespace trace_event_internal { |
| ScopedSyntheticDelay::ScopedSyntheticDelay(const char* name, |
| base::subtle::AtomicWord* impl_ptr) |
| : delay_impl_(GetOrCreateDelay(name, impl_ptr)) { |
| - delay_impl_->Activate(); |
| + delay_impl_->Begin(); |
| } |
| -ScopedSyntheticDelay::~ScopedSyntheticDelay() { delay_impl_->Apply(); } |
| +ScopedSyntheticDelay::~ScopedSyntheticDelay() { delay_impl_->End(); } |
| base::debug::TraceEventSyntheticDelay* GetOrCreateDelay( |
| const char* name, |