Index: base/debug/synthetic_delay.h |
diff --git a/base/debug/synthetic_delay.h b/base/debug/synthetic_delay.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4639bb0d4bc4698a4ee5a180e3de1370c2229944 |
--- /dev/null |
+++ b/base/debug/synthetic_delay.h |
@@ -0,0 +1,130 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+// The synthetic delay framework makes it possible to dynamically inject |
+// arbitrary delays into into different parts of the codebase. This can be used, |
+// for instance, for testing various task scheduling algorithms. |
+// |
+// The delays are specified in terms of a target duration for a given block of |
+// code. If the code executes faster than the duration, the thread is made to |
+// sleep until the deadline is met. |
Dominik Grewe
2013/11/07 16:45:53
Would it be better to busy wait rather than to sle
brianderson
2013/11/18 21:04:06
A sleep should work well if we are just testing th
|
+// |
+// Code can be instrumented for delays with two sets of macros. First, for |
+// delays that should apply within a scope, use the following macro: |
+// |
+// SYNTHETIC_DELAY("cc.LayerTreeHost.DrawAndSwap"); |
+// |
+// For delaying operations that span multiple scopes, use: |
+// |
+// SYNTHETIC_DELAY_BEGIN("cc.Scheduler.BeginMainFrame"); |
+// SYNTHETIC_DELAY_END("cc.Scheduler.BeginMainFrame"); |
+// |
+// Note that while the same delay can be applied in several threads |
+// simultaneously, a single delay operation cannot begin on one thread and end |
+// on another. |
+ |
+#ifndef BASE_DEBUG_SYNTHETIC_DELAY_H_ |
+#define BASE_DEBUG_SYNTHETIC_DELAY_H_ |
+ |
+#include "base/atomicops.h" |
+#include "base/synchronization/lock.h" |
+#include "base/threading/thread_local.h" |
+#include "base/time/time.h" |
+ |
+#define INTERNAL_SYNTHETIC_DELAY_UID3(a, b) synthetic_delay_unique_##a##b |
+#define INTERNAL_SYNTHETIC_DELAY_UID2(a, b) INTERNAL_SYNTHETIC_DELAY_UID3(a, b) |
+#define INTERNAL_SYNTHETIC_DELAY_UID(name_prefix) \ |
+ INTERNAL_SYNTHETIC_DELAY_UID2(name_prefix, __LINE__) |
+ |
+#define SYNTHETIC_DELAY(name) \ |
+ static base::subtle::AtomicWord INTERNAL_SYNTHETIC_DELAY_UID(impl_ptr) = 0; \ |
+ base::debug::ScopedSyntheticDelay INTERNAL_SYNTHETIC_DELAY_UID(delay)( \ |
+ name, &INTERNAL_SYNTHETIC_DELAY_UID(impl_ptr)); |
+ |
+#define SYNTHETIC_DELAY_BEGIN(name) \ |
+ do { \ |
+ static base::subtle::AtomicWord impl_ptr = 0; \ |
+ base::debug::synthetic_delay_internal::GetOrCreateDelay(name, &impl_ptr) \ |
+ ->Begin(); \ |
+ } while (false) |
+ |
+#define SYNTHETIC_DELAY_END(name) \ |
+ do { \ |
+ static base::subtle::AtomicWord impl_ptr = 0; \ |
+ base::debug::synthetic_delay_internal::GetOrCreateDelay(name, &impl_ptr) \ |
+ ->End(); \ |
+ } while (false) |
+ |
+template <typename Type> |
+struct DefaultSingletonTraits; |
+ |
+namespace base { |
+namespace debug { |
+ |
+class SyntheticDelay { |
+ public: |
+ void SetTargetDuration(TimeDelta target_duration); |
+ void Begin(); |
+ void End(); |
+ |
+ private: |
+ SyntheticDelay(); |
+ friend class SyntheticDelayController; |
+ |
+ void Initialize(const char* name); |
+ |
+ struct ThreadState { |
+ base::TimeTicks start_time; |
+ }; |
+ |
+ Lock lock_; |
+ const char* name_; |
+ base::TimeDelta target_duration_; |
+ ThreadLocalPointer<ThreadState> thread_state_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SyntheticDelay); |
+}; |
+ |
+class ScopedSyntheticDelay { |
+ public: |
+ explicit ScopedSyntheticDelay(const char* name, subtle::AtomicWord* impl_ptr); |
+ ~ScopedSyntheticDelay(); |
+ |
+ private: |
+ SyntheticDelay* delay_impl_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ScopedSyntheticDelay); |
+}; |
+ |
+const int kMaxSyntheticDelays = 32; |
+ |
+class SyntheticDelayController { |
brianderson
2013/11/05 03:12:05
Seems like you could move this class into the impl
Sami
2013/11/22 18:29:13
I'll need access to GetOrCreateDelay() later confi
|
+ public: |
+ static SyntheticDelayController* GetInstance(); |
+ |
+ SyntheticDelay* GetOrCreateDelay(const char* name); |
+ |
+ private: |
+ SyntheticDelayController(); |
+ |
+ friend struct DefaultSingletonTraits<SyntheticDelayController>; |
+ |
+ Lock lock_; |
+ SyntheticDelay delays_[kMaxSyntheticDelays]; |
+ SyntheticDelay dummy_delay_; |
+ int delay_count_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SyntheticDelayController); |
+}; |
+ |
+namespace synthetic_delay_internal { |
+ |
+SyntheticDelay* GetOrCreateDelay(const char* name, |
+ subtle::AtomicWord* impl_ptr); |
+ |
+} // namespace synthetic_delay_internal |
+} // namespace debug |
+} // namespace base |
+ |
+#endif /* BASE_DEBUG_SYNTHETIC_DELAY_H_ */ |