1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_
6 #define BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include "base/base_export.h"
12 #include "base/logging.h"
13 
14 namespace base {
15 namespace trace_event {
16 
17 struct TraceCategory;
18 class TraceCategoryTest;
19 class TraceLog;
20 
21 // Allows fast and thread-safe acces to the state of all tracing categories.
22 // All the methods in this class can be concurrently called on multiple threads,
23 // unless otherwise noted (e.g., GetOrCreateCategoryLocked).
24 // The reason why this is a fully static class with global state is to allow to
25 // statically define known categories as global linker-initialized structs,
26 // without requiring static initializers.
27 class BASE_EXPORT CategoryRegistry {
28  public:
29   // Allows for-each iterations over a slice of the categories array.
30   class Range {
31    public:
32     Range(TraceCategory* begin, TraceCategory* end) : begin_(begin), end_(end) {
33       DCHECK_LE(begin, end);
34     }
35     TraceCategory* begin() const { return begin_; }
36     TraceCategory* end() const { return end_; }
37 
38    private:
39     TraceCategory* const begin_;
40     TraceCategory* const end_;
41   };
42 
43   // Known categories.
44   static TraceCategory* const kCategoryExhausted;
45   static TraceCategory* const kCategoryMetadata;
46   static TraceCategory* const kCategoryAlreadyShutdown;
47 
48   // Returns a category entry from the Category.state_ptr() pointer.
49   // TODO(primiano): trace macros should just keep a pointer to the entire
50   // TraceCategory, not just the enabled state pointer. That would remove the
51   // need for this function and make everything cleaner at no extra cost (as
52   // long as the |state_| is the first field of the struct, which can be
53   // guaranteed via static_assert, see TraceCategory ctor).
54   static const TraceCategory* GetCategoryByStatePtr(
55       const uint8_t* category_state);
56 
57   // Returns a category from its name or nullptr if not found.
58   // The output |category| argument is an undefinitely lived pointer to the
59   // TraceCategory owned by the registry. TRACE_EVENTx macros will cache this
60   // pointer and use it for checks in their fast-paths.
61   static TraceCategory* GetCategoryByName(const char* category_name);
62 
63   static bool IsBuiltinCategory(const TraceCategory*);
64 
65  private:
66   friend class TraceCategoryTest;
67   friend class TraceLog;
68   using CategoryInitializerFn = void (*)(TraceCategory*);
69 
70   // Only for debugging/testing purposes, is a no-op on release builds.
71   static void Initialize();
72 
73   // Resets the state of all categories, to clear up the state between tests.
74   static void ResetForTesting();
75 
76   // Used to get/create a category in the slow-path. If the category exists
77   // already, this has the same effect of GetCategoryByName and returns false.
78   // If not, a new category is created and the CategoryInitializerFn is invoked
79   // before retuning true. The caller must guarantee serialization: either call
80   // this method from a single thread or hold a lock when calling this.
81   static bool GetOrCreateCategoryLocked(const char* category_name,
82                                         CategoryInitializerFn,
83                                         TraceCategory**);
84 
85   // Allows to iterate over the valid categories in a for-each loop.
86   // This includes builtin categories such as __metadata.
87   static Range GetAllCategories();
88 };
89 
90 }  // namespace trace_event
91 }  // namespace base
92 
93 #endif  // BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_
94