Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Unified Diff: base/trace_event/event_filter_registry.h

Issue 2557743002: tracing: simplify lifetime of TraceEventFilter(s) (Closed)
Patch Set: rebase Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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_

Powered by Google App Engine
This is Rietveld 408576698