Chromium Code Reviews| Index: components/metrics/leak_detector/leak_detector.h |
| diff --git a/components/metrics/leak_detector/leak_detector.h b/components/metrics/leak_detector/leak_detector.h |
| index e23609444490d78765744910f02334b6f7fbbc8f..a45ad525f2b2c6ac4e7cce0603bf0e93c2581b42 100644 |
| --- a/components/metrics/leak_detector/leak_detector.h |
| +++ b/components/metrics/leak_detector/leak_detector.h |
| @@ -14,23 +14,27 @@ |
| #include "base/feature_list.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/macros.h" |
| -#include "base/memory/weak_ptr.h" |
| +#include "base/memory/scoped_ptr.h" |
| #include "base/observer_list.h" |
| +#include "base/synchronization/lock.h" |
| #include "base/threading/thread_checker.h" |
| +namespace base { |
| +template <typename T> struct DefaultLazyInstanceTraits; |
| +} |
| + |
| namespace metrics { |
| +namespace leak_detector { |
| +class LeakDetectorImpl; |
| +} |
| + |
| // LeakDetector is an interface layer that connects the allocator |
| // (base::allocator), the leak detector logic (LeakDetectorImpl), and any |
| // external classes interested in receiving leak reports (extend the Observer |
| // class). |
| // |
| -// Currently it is stubbed out and only provides an interface for registering |
| -// observers to receive leak reports. |
| -// TODO(sque): Add the full functionality and allow only one instance. |
| -// |
| -// This class is not thread-safe, and it should always be called on the same |
| -// thread that instantiated it. |
| +// This class is thread-safe as it uses locks for critical sections. |
|
Will Harris
2016/03/12 01:44:22
it looks like only addobserver and removeobserver
Simon Que
2016/03/14 19:17:01
Done.
|
| class LeakDetector { |
| public: |
| // Contains a report of a detected memory leak. |
| @@ -54,7 +58,10 @@ class LeakDetector { |
| virtual void OnLeakFound(const LeakReport& report) = 0; |
| }; |
| - // Constructor arguments: |
| + // Returns the sole instance, or creates it if it hasn't already been created. |
| + static LeakDetector* GetInstance(); |
| + |
| + // Initializer arguments: |
| // sampling_rate: |
| // Pseudorandomly sample a fraction of the incoming allocations and frees, |
| // based on hash values. Setting to 0 means no allocs/frees are sampled. |
| @@ -70,13 +77,11 @@ class LeakDetector { |
| // A possible leak should be suspected this many times to take action on i |
| // For size analysis, the action is to start profiling by call stack. |
| // For call stack analysis, the action is to generate a leak report. |
| - LeakDetector(float sampling_rate, |
| - size_t max_call_stack_unwind_depth, |
| - uint64_t analysis_interval_bytes, |
| - uint32_t size_suspicion_threshold, |
| - uint32_t call_stack_suspicion_threshold); |
| - |
| - ~LeakDetector(); |
| + void Init(float sampling_rate, |
| + size_t max_call_stack_unwind_depth, |
| + uint64_t analysis_interval_bytes, |
| + uint32_t size_suspicion_threshold, |
| + uint32_t call_stack_suspicion_threshold); |
| // Add |observer| to the list of stored Observers, i.e. |observers_|, to which |
| // the leak detector will report leaks. |
| @@ -86,8 +91,28 @@ class LeakDetector { |
| void RemoveObserver(Observer* observer); |
| private: |
| + friend base::DefaultLazyInstanceTraits<LeakDetector>; |
| FRIEND_TEST_ALL_PREFIXES(LeakDetectorTest, NotifyObservers); |
| + // Keep these private, as this class is meant to be initialized only through |
| + // the lazy instance, and never destroyed. |
| + LeakDetector(); |
| + ~LeakDetector(); |
| + |
| + // Allocator hook function that processes each alloc. Performs sampling and |
| + // unwinds call stack if necessary. Passes the allocated memory |ptr| and |
| + // allocation size |size| along with call stack info to RecordAlloc(). |
| + static void AllocHook(const void* ptr, size_t size); |
| + |
| + // Allocator hook function that processes each free. Performs sampling and |
| + // passes the allocation address |ptr| to |impl_|. |
| + static void FreeHook(const void* ptr); |
| + |
| + // Give an pointer |ptr|, computes a hash of the pointer value and compares it |
| + // against |sampling_factor_| to determine if it should be sampled. This |
| + // allows the same pointer to be sampled during both alloc and free. |
| + bool ShouldSample(const void* ptr) const; |
| + |
| // Notifies all Observers in |observers_| with the given vector of leak |
| // reports. |
| void NotifyObservers(const std::vector<LeakReport>& reports); |
| @@ -95,11 +120,40 @@ class LeakDetector { |
| // List of observers to notify when there's a leak report. |
| base::ObserverList<Observer> observers_; |
| + // For atomic access to |observers_|. |
| + base::Lock observers_lock_; |
| + |
| + // Handles leak detection logic. Must be called under lock as LeakDetectorImpl |
| + // uses shared resources. |
| + scoped_ptr<leak_detector::LeakDetectorImpl> impl_; |
| + |
| + // For atomic access to |impl_|. |
| + base::Lock impl_lock_; |
| + |
| // For thread safety. |
| base::ThreadChecker thread_checker_; |
| - // For generating closures containing objects of this class. |
| - base::WeakPtrFactory<LeakDetector> weak_factory_; |
| + // Total number of bytes allocated, computed before sampling. |
| + size_t total_alloc_size_; |
| + |
| + // The value of |total_alloc_size_| the last time there was a leak analysis, |
| + // rounded down to the nearest multiple of |analysis_interval_bytes_|. |
| + size_t last_analysis_alloc_size_; |
| + |
| + // For atomic access to |total_alloc_size_| and |last_analysis_alloc_size_|. |
| + base::Lock alloc_size_lock_; |
| + |
| + // Perform a leak analysis each time this many bytes have been allocated since |
| + // the previous analysis. |
| + size_t analysis_interval_bytes_; |
| + |
| + // When unwinding call stacks, unwind no more than this number of frames. |
| + size_t max_call_stack_unwind_depth_; |
| + |
| + // Sampling factor used by ShouldSample(). It's full range of values |
| + // corresponds to the allowable range of |sampling_rate| passed in during |
| + // initialization: [0.0f, 1.0f] -> [0, UINT64_MAX]. |
| + uint64_t sampling_factor_; |
| DISALLOW_COPY_AND_ASSIGN(LeakDetector); |
| }; |