| // Copyright 2016 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_ |
| #define BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_ |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <atomic> |
| |
| #include "base/base_export.h" |
| #include "base/check_op.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/trace_event/builtin_categories.h" |
| #include "base/trace_event/common/trace_event_common.h" |
| #include "base/trace_event/trace_category.h" |
| #include "build/build_config.h" |
| |
| namespace base { |
| namespace trace_event { |
| |
| class TraceCategoryTest; |
| class TraceLog; |
| |
| // Allows fast and thread-safe acces to the state of all tracing categories. |
| // All the methods in this class can be concurrently called on multiple threads, |
| // unless otherwise noted (e.g., GetOrCreateCategoryLocked). |
| // The reason why this is a fully static class with global state is to allow to |
| // statically define known categories as global linker-initialized structs, |
| // without requiring static initializers. |
| class BASE_EXPORT CategoryRegistry { |
| public: |
| // Allows for-each iterations over a slice of the categories array. |
| class Range { |
| public: |
| Range(TraceCategory* begin, TraceCategory* end) : begin_(begin), end_(end) { |
| DCHECK_LE(begin, end); |
| } |
| TraceCategory* begin() const { return begin_; } |
| TraceCategory* end() const { return end_; } |
| |
| private: |
| const raw_ptr<TraceCategory, DanglingUntriaged> begin_; |
| const raw_ptr<TraceCategory, DanglingUntriaged> end_; |
| }; |
| |
| // Known categories. |
| static TraceCategory* const kCategoryExhausted; |
| static TraceCategory* const kCategoryMetadata; |
| static TraceCategory* const kCategoryAlreadyShutdown; |
| |
| // Returns a category entry from the Category.state_ptr() pointer. |
| // TODO(primiano): trace macros should just keep a pointer to the entire |
| // TraceCategory, not just the enabled state pointer. That would remove the |
| // need for this function and make everything cleaner at no extra cost (as |
| // long as the |state_| is the first field of the struct, which can be |
| // guaranteed via static_assert, see TraceCategory ctor). |
| static const TraceCategory* GetCategoryByStatePtr( |
| const uint8_t* category_state); |
| |
| // Returns a category from its name or nullptr if not found. |
| // The output |category| argument is an undefinitely lived pointer to the |
| // TraceCategory owned by the registry. TRACE_EVENTx macros will cache this |
| // pointer and use it for checks in their fast-paths. |
| static TraceCategory* GetCategoryByName(const char* category_name); |
| |
| // Returns a built-in category from its name or nullptr if not found at |
| // compile-time. The return value is an undefinitely lived pointer to the |
| // TraceCategory owned by the registry. |
| static constexpr TraceCategory* GetBuiltinCategoryByName( |
| const char* category_group) { |
| #if BUILDFLAG(IS_WIN) && defined(COMPONENT_BUILD) |
| // The address cannot be evaluated at compile-time in Windows component |
| // builds. |
| return nullptr; |
| #else |
| for (size_t i = 0; i < BuiltinCategories::Size(); ++i) { |
| if (StrEqConstexpr(category_group, BuiltinCategories::At(i))) |
| return &categories_[i]; |
| } |
| return nullptr; |
| #endif |
| } |
| |
| // Returns whether |category| points at one of the meta categories that |
| // shouldn't be displayed in the tracing UI. |
| static bool IsMetaCategory(const TraceCategory* category); |
| |
| private: |
| friend class TraceCategoryTest; |
| friend class TraceLog; |
| using CategoryInitializerFn = void (*)(TraceCategory*); |
| |
| // The max number of trace categories that can be recorded. |
| static constexpr size_t kMaxCategories = 350; |
| |
| // Checks that there is enough space for all builtin categories. |
| static_assert(BuiltinCategories::Size() <= kMaxCategories, |
| "kMaxCategories must be greater than kNumBuiltinCategories"); |
| |
| // Only for debugging/testing purposes, is a no-op on release builds. |
| static void Initialize(); |
| |
| // Resets the state of all categories, to clear up the state between tests. |
| static void ResetForTesting(); |
| |
| // Used to get/create a category in the slow-path. If the category exists |
| // already, this has the same effect of GetCategoryByName and returns false. |
| // If not, a new category is created and the CategoryInitializerFn is invoked |
| // before retuning true. The caller must guarantee serialization: either call |
| // this method from a single thread or hold a lock when calling this. |
| static bool GetOrCreateCategoryLocked(const char* category_name, |
| CategoryInitializerFn, |
| TraceCategory**); |
| |
| // Allows to iterate over the valid categories in a for-each loop. |
| // This includes builtin categories such as __metadata. |
| static Range GetAllCategories(); |
| |
| // Returns whether |category| correctly points at |categories_| array entry. |
| static bool IsValidCategoryPtr(const TraceCategory* category); |
| |
| // The static array of trace categories. |
| static TraceCategory categories_[kMaxCategories]; |
| |
| // Contains the number of created categories. |
| static std::atomic<size_t> category_index_; |
| }; |
| |
| } // namespace trace_event |
| } // namespace base |
| |
| #endif // BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_ |