Chromium Code Reviews| Index: base/trace_event/event_filter_registry.h |
| diff --git a/base/trace_event/event_filter_registry.h b/base/trace_event/event_filter_registry.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..bbb2697223b1663f455da2b71a886dcb4f880cd5 |
| --- /dev/null |
| +++ b/base/trace_event/event_filter_registry.h |
| @@ -0,0 +1,108 @@ |
| +// Copyright 2016 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 BASE_TRACE_EVENT_EVENT_FILTER_REGISTRY_H_ |
| +#define BASE_TRACE_EVENT_EVENT_FILTER_REGISTRY_H_ |
| + |
| +#include <stddef.h> |
| +#include <stdint.h> |
| + |
| +#include <memory> |
| + |
| +#include "base/base_export.h" |
| +#include "base/logging.h" |
| +#include "base/macros.h" |
| + |
| +namespace base { |
| +namespace trace_event { |
| + |
| +class TraceEventFilter; |
| + |
| +// Keeps track of all filters and manages their lifetime in a circular FIFO. |
| +// |
| +// When a filter is registered via RegisterFilter(): |
| +// the registry takes ownership and guarantees that: (1) the filter will live at |
| +// least until the unregister call; (2) the index of the filter, returned by |
| +// Iterator.GetIndex(), will be stable throughout all the lifetime of the |
| +// filter. (2) allows TraceCategory instances to keep a fast and cheap bitmap |
| +// cache of enabled filters. |
| +// |
| +// When UnregisterAllFilters() is called: |
| +// the registry stops immediately returning any filter from GetActiveFilters() |
| +// but does NOT destroy any filter. Instead it will delay the destruction of |
| +// each filter until other kMaxFilters filters are re-added to the registry. |
| +// |
| +// The rationale of this lifetime model is: at the time UnregisterAllFilters() |
| +// is called some TRACE_EVENT macros might still be using the filters on other |
| +// threads. We can't take locks or use atomics when invoking those filters as |
| +// it would impact performance of TRACE_EVENT macros. So we defer their |
| +// destruction until the very last moment. |
|
ssid
2016/12/12 04:50:18
When I proposed the model of leaking filters to Oy
Primiano Tucci (use gerrit)
2016/12/12 14:38:54
Even if each filter contains a whitelist of 100 st
ssid
2016/12/12 21:25:53
So, I think we could just destroy at SetEnabled. W
|
| +class BASE_EXPORT EventFilterRegistry { |
| + public: |
| + // Usage: for (auto it = GetActiveFilters(); it.IsValid(); it.MoveNext()). |
| + // Not worth the complexity of a full std::iterator. |
| + class Iterator { |
| + public: |
| + bool IsValid() const; |
| + void MoveNext(); |
| + uint32_t GetIndex() const; |
| + const TraceEventFilter* operator->() const; |
| + const TraceEventFilter& operator*() const { return *(operator->()); }; |
| + |
| + private: |
| + friend class EventFilterRegistry; |
| + Iterator(uint32_t start, uint32_t pos); |
| + |
| + // The position of the cursor in the ring buffer at the time |
| + // GetActiveFilters() was called. |
| + const uint32_t start_; |
| + |
| + // Offset in the buffer relative to start_. 0 <= offset < kMaxFilters. |
| + uint32_t offset_; |
| + }; |
| + |
| + // Returns a filter from its index (obtained through Iterator::GetIndex()). |
| + static TraceEventFilter* Get(uint32_t index) { |
| + DCHECK_LT(index, kMaxFilters); |
| + DCHECK(filters_[index].filter); |
| + return filters_[index].filter; |
| + } |
| + |
| + // Calls to the methods below must be serialized by the caller: |
| + // either called on the same thread or holding a lock. |
| + |
| + // Registers a filter and guarantees to keep it alive at least until the |
| + // unregistration. It causes a crash via CHECK() if attempting to register |
| + // more more than kMaxFilters. |
| + static void RegisterFilter(std::unique_ptr<TraceEventFilter>); |
| + |
| + // Unregisters all filters without destroying them. |
| + static void UnregisterAllFilters(); |
| + |
| + // Returns a sequence of filters that have not been unregistered. |
| + static Iterator GetActiveFilters(); |
| + |
| + static void ResetForTesting(); |
| + |
| + private: |
| + struct FilterEntry { |
| + // Owned pointer to the filter instance. When nullptr indicates a free slot. |
| + // Can't be a unique_ptr as that would create static initializers. |
| + TraceEventFilter* filter; |
| + |
| + // When false it indicates that the filter has been unregister and hence the |
| + // |filter| can be freed and the slot reused. |
| + bool active; |
| + }; |
| + static constexpr uint32_t kMaxFilters = 32; |
| + static FilterEntry filters_[kMaxFilters]; |
|
ssid
2016/12/12 04:50:18
Should you annotate this object as leaked, or the
Primiano Tucci (use gerrit)
2016/12/12 14:38:54
I discovered recently that ASan doesn't complain a
ssid
2016/12/12 21:25:53
Okay thanks!
|
| + static uint32_t filters_index_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(EventFilterRegistry); |
| +}; |
| + |
| +} // namespace trace_event |
| +} // namespace base |
| + |
| +#endif // BASE_TRACE_EVENT_EVENT_FILTER_REGISTRY_H_ |