| // Copyright 2015 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. |
| |
| #ifndef COMPONENTS_METRICS_LEAK_DETECTOR_RANKED_SET_H_ |
| #define COMPONENTS_METRICS_LEAK_DETECTOR_RANKED_SET_H_ |
| |
| #include <stddef.h> |
| |
| #include <functional> // for std::less |
| #include <set> |
| |
| #include "base/macros.h" |
| #include "components/metrics/leak_detector/custom_allocator.h" |
| #include "components/metrics/leak_detector/leak_detector_value_type.h" |
| #include "components/metrics/leak_detector/stl_allocator.h" |
| |
| namespace metrics { |
| namespace leak_detector { |
| |
| // RankedSet lets you add entries consisting of a value-count pair, and |
| // automatically sorts them internally by count in descending order. This allows |
| // for the user of this container to insert value-count pairs without having to |
| // explicitly sort them by count. |
| class RankedSet { |
| public: |
| using ValueType = LeakDetectorValueType; |
| |
| // A single entry in the RankedSet. The RankedSet sorts entries by |count| |
| // in descending order. |
| struct Entry { |
| ValueType value; |
| int count; |
| |
| // This less-than comparator is used for sorting Entries within a sorted |
| // container. It internally reverses the comparison so that higher-count |
| // entries are sorted ahead of lower-count entries. |
| bool operator<(const Entry& other) const; |
| }; |
| |
| // This class uses CustomAllocator to avoid recursive malloc hook invocation |
| // when analyzing allocs and frees. |
| using EntrySet = |
| std::set<Entry, std::less<Entry>, STLAllocator<Entry, CustomAllocator>>; |
| using const_iterator = EntrySet::const_iterator; |
| |
| explicit RankedSet(size_t max_size); |
| ~RankedSet(); |
| |
| // For move semantics. |
| RankedSet(RankedSet&& other); |
| RankedSet& operator=(RankedSet&& other); |
| |
| // Accessors for begin() and end() const iterators. |
| const_iterator begin() const { return entries_.begin(); } |
| const_iterator end() const { return entries_.end(); } |
| |
| size_t size() const { return entries_.size(); } |
| size_t max_size() const { return max_size_; } |
| |
| // Add a new value-count pair to the container. Will overwrite any existing |
| // entry with the same value and count. Will not overwrite an existing entry |
| // with the same value but a different count, or different values with the |
| // same count. |
| // |
| // Time complexity is O(log n). |
| void Add(const ValueType& value, int count); |
| |
| // Helper functions to directly add a size or call stack to the RankedSet. |
| void AddSize(size_t size, int count) { Add(ValueType(size), count); } |
| void AddCallStack(const CallStack* call_stack, int count) { |
| Add(ValueType(call_stack), count); |
| } |
| |
| // Helper functions to directly search for an element with |value| equal to a |
| // particular size or call stack. The time complexity is O(n) rather than the |
| // O(log n) typical of std::set. These should be called sparingly in |
| // performance-critical code. |
| const_iterator FindSize(size_t size) const { return Find(ValueType(size)); } |
| const_iterator FindCallStack(const CallStack* call_stack) const { |
| return Find(ValueType(call_stack)); |
| } |
| |
| private: |
| // Returns an iterator to the element in |entries_| with value=|value|, or to |
| // entries_.end() if it was not found. |
| const_iterator Find(const ValueType& value) const; |
| |
| // Max and min counts. Returns 0 if the list is empty. |
| int max_count() const { |
| return entries_.empty() ? 0 : entries_.begin()->count; |
| } |
| int min_count() const { |
| return entries_.empty() ? 0 : entries_.rbegin()->count; |
| } |
| |
| // Max number of items that can be stored in the list. |
| size_t max_size_; |
| |
| // Actual storage container for entries. |
| EntrySet entries_; |
| |
| DISALLOW_COPY_AND_ASSIGN(RankedSet); |
| }; |
| |
| } // namespace leak_detector |
| } // namespace metrics |
| |
| #endif // COMPONENTS_METRICS_LEAK_DETECTOR_RANKED_SET_H_ |