| 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..319e38695949e7a2137d76ecd802cc22a740f61b 100644
|
| --- a/components/metrics/leak_detector/leak_detector.h
|
| +++ b/components/metrics/leak_detector/leak_detector.h
|
| @@ -14,23 +14,38 @@
|
| #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.
|
| +// Only one instance of this class can exist. Access this instance using
|
| +// GetInstance(). Do not create an instance of this class directly.
|
| +//
|
| +// These member functions are thread-safe:
|
| +// - AllocHook
|
| +// - FreeHook
|
| +// - AddObserver
|
| +// - RemoveObserver
|
| //
|
| -// This class is not thread-safe, and it should always be called on the same
|
| -// thread that instantiated it.
|
| +// All other functions must always be called from the same thread. This is
|
| +// enforced with a DCHECK.
|
| class LeakDetector {
|
| public:
|
| // Contains a report of a detected memory leak.
|
| @@ -54,7 +69,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 +88,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,20 +102,68 @@ 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);
|
|
|
| // List of observers to notify when there's a leak report.
|
| + // TODO(sque): Consider using ObserverListThreadSafe instead.
|
| 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 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 |impl_|, |total_alloc_size_| and
|
| + // |last_analysis_alloc_size_|.
|
| + base::Lock recording_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);
|
| };
|
|
|