1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #ifndef INCLUDE_PERFETTO_TRACING_TRACED_VALUE_H_
18*6dbdd20aSAndroid Build Coastguard Worker #define INCLUDE_PERFETTO_TRACING_TRACED_VALUE_H_
19*6dbdd20aSAndroid Build Coastguard Worker
20*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/compiler.h"
21*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/export.h"
22*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/template_util.h"
23*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/protozero/message.h"
24*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/protozero/proto_utils.h"
25*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/tracing/internal/checked_scope.h"
26*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/tracing/string_helpers.h"
27*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/tracing/traced_value_forward.h"
28*6dbdd20aSAndroid Build Coastguard Worker
29*6dbdd20aSAndroid Build Coastguard Worker #include <memory>
30*6dbdd20aSAndroid Build Coastguard Worker #include <string>
31*6dbdd20aSAndroid Build Coastguard Worker #include <string_view>
32*6dbdd20aSAndroid Build Coastguard Worker #include <type_traits>
33*6dbdd20aSAndroid Build Coastguard Worker #include <utility>
34*6dbdd20aSAndroid Build Coastguard Worker
35*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
36*6dbdd20aSAndroid Build Coastguard Worker
37*6dbdd20aSAndroid Build Coastguard Worker namespace protos {
38*6dbdd20aSAndroid Build Coastguard Worker namespace pbzero {
39*6dbdd20aSAndroid Build Coastguard Worker class DebugAnnotation;
40*6dbdd20aSAndroid Build Coastguard Worker }
41*6dbdd20aSAndroid Build Coastguard Worker } // namespace protos
42*6dbdd20aSAndroid Build Coastguard Worker
43*6dbdd20aSAndroid Build Coastguard Worker class DebugAnnotation;
44*6dbdd20aSAndroid Build Coastguard Worker class EventContext;
45*6dbdd20aSAndroid Build Coastguard Worker
46*6dbdd20aSAndroid Build Coastguard Worker // These classes provide a JSON-inspired way to write structed data into traces.
47*6dbdd20aSAndroid Build Coastguard Worker //
48*6dbdd20aSAndroid Build Coastguard Worker // Each TracedValue can be consumed exactly once to write a value into a trace
49*6dbdd20aSAndroid Build Coastguard Worker // using one of the Write* methods.
50*6dbdd20aSAndroid Build Coastguard Worker //
51*6dbdd20aSAndroid Build Coastguard Worker // Write* methods fall into two categories:
52*6dbdd20aSAndroid Build Coastguard Worker // - Primitive types (int, string, bool, double, etc): they just write the
53*6dbdd20aSAndroid Build Coastguard Worker // provided value, consuming the TracedValue in the process.
54*6dbdd20aSAndroid Build Coastguard Worker // - Complex types (arrays and dicts): they consume the TracedValue and
55*6dbdd20aSAndroid Build Coastguard Worker // return a corresponding scoped object (TracedArray or TracedDictionary).
56*6dbdd20aSAndroid Build Coastguard Worker // This scope then can be used to write multiple items into the container:
57*6dbdd20aSAndroid Build Coastguard Worker // TracedArray::AppendItem and TracedDictionary::AddItem return a new
58*6dbdd20aSAndroid Build Coastguard Worker // TracedValue which then can be used to write an element of the
59*6dbdd20aSAndroid Build Coastguard Worker // dictionary or array.
60*6dbdd20aSAndroid Build Coastguard Worker //
61*6dbdd20aSAndroid Build Coastguard Worker // To define how a custom class should be written into the trace, users should
62*6dbdd20aSAndroid Build Coastguard Worker // define one of the two following functions:
63*6dbdd20aSAndroid Build Coastguard Worker // - Foo::WriteIntoTrace(TracedValue) const
64*6dbdd20aSAndroid Build Coastguard Worker // (preferred for code which depends on perfetto directly)
65*6dbdd20aSAndroid Build Coastguard Worker // - perfetto::TraceFormatTraits<T>::WriteIntoTrace(
66*6dbdd20aSAndroid Build Coastguard Worker // TracedValue, const T&);
67*6dbdd20aSAndroid Build Coastguard Worker // (should be used if T is defined in a library which doesn't know anything
68*6dbdd20aSAndroid Build Coastguard Worker // about tracing).
69*6dbdd20aSAndroid Build Coastguard Worker //
70*6dbdd20aSAndroid Build Coastguard Worker //
71*6dbdd20aSAndroid Build Coastguard Worker // After defining a conversion method, the object can be used directly as a
72*6dbdd20aSAndroid Build Coastguard Worker // TRACE_EVENT argument:
73*6dbdd20aSAndroid Build Coastguard Worker //
74*6dbdd20aSAndroid Build Coastguard Worker // Foo foo;
75*6dbdd20aSAndroid Build Coastguard Worker // TRACE_EVENT("cat", "Event", "arg", foo);
76*6dbdd20aSAndroid Build Coastguard Worker //
77*6dbdd20aSAndroid Build Coastguard Worker // Examples:
78*6dbdd20aSAndroid Build Coastguard Worker //
79*6dbdd20aSAndroid Build Coastguard Worker // TRACE_EVENT("cat", "event", "params", [&](perfetto::TracedValue context)
80*6dbdd20aSAndroid Build Coastguard Worker // {
81*6dbdd20aSAndroid Build Coastguard Worker // auto dict = std::move(context).WriteDictionary();
82*6dbdd20aSAndroid Build Coastguard Worker // dict->Add("param1", param1);
83*6dbdd20aSAndroid Build Coastguard Worker // dict->Add("param2", param2);
84*6dbdd20aSAndroid Build Coastguard Worker // ...
85*6dbdd20aSAndroid Build Coastguard Worker // dict->Add("paramN", paramN);
86*6dbdd20aSAndroid Build Coastguard Worker //
87*6dbdd20aSAndroid Build Coastguard Worker // {
88*6dbdd20aSAndroid Build Coastguard Worker // auto inner_array = dict->AddArray("inner");
89*6dbdd20aSAndroid Build Coastguard Worker // inner_array->Append(value1);
90*6dbdd20aSAndroid Build Coastguard Worker // inner_array->Append(value2);
91*6dbdd20aSAndroid Build Coastguard Worker // }
92*6dbdd20aSAndroid Build Coastguard Worker // });
93*6dbdd20aSAndroid Build Coastguard Worker //
94*6dbdd20aSAndroid Build Coastguard Worker // template <typename T>
95*6dbdd20aSAndroid Build Coastguard Worker // TraceFormatTraits<std::optional<T>>::WriteIntoTrace(
96*6dbdd20aSAndroid Build Coastguard Worker // TracedValue context, const std::optional<T>& value) {
97*6dbdd20aSAndroid Build Coastguard Worker // if (!value) {
98*6dbdd20aSAndroid Build Coastguard Worker // std::move(context).WritePointer(nullptr);
99*6dbdd20aSAndroid Build Coastguard Worker // return;
100*6dbdd20aSAndroid Build Coastguard Worker // }
101*6dbdd20aSAndroid Build Coastguard Worker // perfetto::WriteIntoTrace(std::move(context), *value);
102*6dbdd20aSAndroid Build Coastguard Worker // }
103*6dbdd20aSAndroid Build Coastguard Worker //
104*6dbdd20aSAndroid Build Coastguard Worker // template <typename T>
105*6dbdd20aSAndroid Build Coastguard Worker // TraceFormatTraits<std::vector<T>>::WriteIntoTrace(
106*6dbdd20aSAndroid Build Coastguard Worker // TracedValue context, const std::array<T>& value) {
107*6dbdd20aSAndroid Build Coastguard Worker // auto array = std::move(context).WriteArray();
108*6dbdd20aSAndroid Build Coastguard Worker // for (const auto& item: value) {
109*6dbdd20aSAndroid Build Coastguard Worker // array_scope.Append(item);
110*6dbdd20aSAndroid Build Coastguard Worker // }
111*6dbdd20aSAndroid Build Coastguard Worker // }
112*6dbdd20aSAndroid Build Coastguard Worker //
113*6dbdd20aSAndroid Build Coastguard Worker // class Foo {
114*6dbdd20aSAndroid Build Coastguard Worker // void WriteIntoTrace(TracedValue context) const {
115*6dbdd20aSAndroid Build Coastguard Worker // auto dict = std::move(context).WriteDictionary();
116*6dbdd20aSAndroid Build Coastguard Worker // dict->Set("key", 42);
117*6dbdd20aSAndroid Build Coastguard Worker // dict->Set("foo", "bar");
118*6dbdd20aSAndroid Build Coastguard Worker // dict->Set("member", member_);
119*6dbdd20aSAndroid Build Coastguard Worker // }
120*6dbdd20aSAndroid Build Coastguard Worker // }
121*6dbdd20aSAndroid Build Coastguard Worker namespace internal {
122*6dbdd20aSAndroid Build Coastguard Worker // TODO(altimin): Currently EventContext can be null due the need to support
123*6dbdd20aSAndroid Build Coastguard Worker // TracedValue-based serialisation with the Chrome's TraceLog. After this is
124*6dbdd20aSAndroid Build Coastguard Worker // gone, the second parameter should be changed to EventContext&.
125*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_EXPORT_COMPONENT TracedValue
126*6dbdd20aSAndroid Build Coastguard Worker CreateTracedValueFromProto(protos::pbzero::DebugAnnotation*,
127*6dbdd20aSAndroid Build Coastguard Worker EventContext* = nullptr);
128*6dbdd20aSAndroid Build Coastguard Worker }
129*6dbdd20aSAndroid Build Coastguard Worker
130*6dbdd20aSAndroid Build Coastguard Worker class PERFETTO_EXPORT_COMPONENT TracedValue {
131*6dbdd20aSAndroid Build Coastguard Worker public:
132*6dbdd20aSAndroid Build Coastguard Worker TracedValue(const TracedValue&) = delete;
133*6dbdd20aSAndroid Build Coastguard Worker TracedValue& operator=(const TracedValue&) = delete;
134*6dbdd20aSAndroid Build Coastguard Worker TracedValue& operator=(TracedValue&&) = delete;
135*6dbdd20aSAndroid Build Coastguard Worker TracedValue(TracedValue&&);
136*6dbdd20aSAndroid Build Coastguard Worker ~TracedValue();
137*6dbdd20aSAndroid Build Coastguard Worker
138*6dbdd20aSAndroid Build Coastguard Worker // TracedValue represents a context into which a single value can be written
139*6dbdd20aSAndroid Build Coastguard Worker // (either by writing it directly for primitive types, or by creating a
140*6dbdd20aSAndroid Build Coastguard Worker // TracedArray or TracedDictionary for the complex types). This is enforced
141*6dbdd20aSAndroid Build Coastguard Worker // by allowing Write* methods to be called only on rvalue references.
142*6dbdd20aSAndroid Build Coastguard Worker
143*6dbdd20aSAndroid Build Coastguard Worker void WriteInt64(int64_t value) &&;
144*6dbdd20aSAndroid Build Coastguard Worker void WriteUInt64(uint64_t value) &&;
145*6dbdd20aSAndroid Build Coastguard Worker void WriteDouble(double value) &&;
146*6dbdd20aSAndroid Build Coastguard Worker void WriteBoolean(bool value) &&;
147*6dbdd20aSAndroid Build Coastguard Worker void WriteString(const char*) &&;
148*6dbdd20aSAndroid Build Coastguard Worker void WriteString(const char*, size_t len) &&;
149*6dbdd20aSAndroid Build Coastguard Worker void WriteString(const std::string&) &&;
150*6dbdd20aSAndroid Build Coastguard Worker void WriteString(std::string_view) &&;
151*6dbdd20aSAndroid Build Coastguard Worker void WritePointer(const void* value) &&;
152*6dbdd20aSAndroid Build Coastguard Worker template <typename MessageType>
153*6dbdd20aSAndroid Build Coastguard Worker TracedProto<MessageType> WriteProto() &&;
154*6dbdd20aSAndroid Build Coastguard Worker
155*6dbdd20aSAndroid Build Coastguard Worker // Rules for writing nested dictionaries and arrays:
156*6dbdd20aSAndroid Build Coastguard Worker // - Only one scope (TracedArray, TracedDictionary or TracedValue) can be
157*6dbdd20aSAndroid Build Coastguard Worker // active at the same time. It's only allowed to call methods on the active
158*6dbdd20aSAndroid Build Coastguard Worker // scope.
159*6dbdd20aSAndroid Build Coastguard Worker // - When a scope creates a nested scope, the new scope becomes active.
160*6dbdd20aSAndroid Build Coastguard Worker // - When a scope is destroyed, its parent scope becomes active again.
161*6dbdd20aSAndroid Build Coastguard Worker //
162*6dbdd20aSAndroid Build Coastguard Worker // Typically users will have to create a scope only at the beginning of a
163*6dbdd20aSAndroid Build Coastguard Worker // conversion function and this scope should be destroyed at the end of it.
164*6dbdd20aSAndroid Build Coastguard Worker // TracedArray::Append and TracedDictionary::Add create, write and complete
165*6dbdd20aSAndroid Build Coastguard Worker // inner scopes automatically.
166*6dbdd20aSAndroid Build Coastguard Worker
167*6dbdd20aSAndroid Build Coastguard Worker // Scope which allows multiple values to be appended.
168*6dbdd20aSAndroid Build Coastguard Worker TracedArray WriteArray() && PERFETTO_WARN_UNUSED_RESULT;
169*6dbdd20aSAndroid Build Coastguard Worker
170*6dbdd20aSAndroid Build Coastguard Worker // Scope which allows multiple key-value pairs to be added.
171*6dbdd20aSAndroid Build Coastguard Worker TracedDictionary WriteDictionary() && PERFETTO_WARN_UNUSED_RESULT;
172*6dbdd20aSAndroid Build Coastguard Worker
173*6dbdd20aSAndroid Build Coastguard Worker private:
174*6dbdd20aSAndroid Build Coastguard Worker friend class TracedArray;
175*6dbdd20aSAndroid Build Coastguard Worker friend class TracedDictionary;
176*6dbdd20aSAndroid Build Coastguard Worker friend TracedValue internal::CreateTracedValueFromProto(
177*6dbdd20aSAndroid Build Coastguard Worker protos::pbzero::DebugAnnotation*,
178*6dbdd20aSAndroid Build Coastguard Worker EventContext*);
179*6dbdd20aSAndroid Build Coastguard Worker
180*6dbdd20aSAndroid Build Coastguard Worker static TracedValue CreateFromProto(protos::pbzero::DebugAnnotation* proto,
181*6dbdd20aSAndroid Build Coastguard Worker EventContext* event_context = nullptr);
182*6dbdd20aSAndroid Build Coastguard Worker
TracedValue(protos::pbzero::DebugAnnotation * annotation,EventContext * event_context,internal::CheckedScope * parent_scope)183*6dbdd20aSAndroid Build Coastguard Worker inline TracedValue(protos::pbzero::DebugAnnotation* annotation,
184*6dbdd20aSAndroid Build Coastguard Worker EventContext* event_context,
185*6dbdd20aSAndroid Build Coastguard Worker internal::CheckedScope* parent_scope)
186*6dbdd20aSAndroid Build Coastguard Worker : annotation_(annotation),
187*6dbdd20aSAndroid Build Coastguard Worker event_context_(event_context),
188*6dbdd20aSAndroid Build Coastguard Worker checked_scope_(parent_scope) {}
189*6dbdd20aSAndroid Build Coastguard Worker
190*6dbdd20aSAndroid Build Coastguard Worker protozero::Message* WriteProtoInternal(const char* name);
191*6dbdd20aSAndroid Build Coastguard Worker
192*6dbdd20aSAndroid Build Coastguard Worker // Temporary support for perfetto::DebugAnnotation C++ class before it's going
193*6dbdd20aSAndroid Build Coastguard Worker // to be replaced by TracedValue.
194*6dbdd20aSAndroid Build Coastguard Worker // TODO(altimin): Convert v8 to use TracedValue directly and delete it.
195*6dbdd20aSAndroid Build Coastguard Worker friend class DebugAnnotation;
196*6dbdd20aSAndroid Build Coastguard Worker
197*6dbdd20aSAndroid Build Coastguard Worker protos::pbzero::DebugAnnotation* const annotation_ = nullptr;
198*6dbdd20aSAndroid Build Coastguard Worker EventContext* const event_context_ = nullptr;
199*6dbdd20aSAndroid Build Coastguard Worker
200*6dbdd20aSAndroid Build Coastguard Worker internal::CheckedScope checked_scope_;
201*6dbdd20aSAndroid Build Coastguard Worker };
202*6dbdd20aSAndroid Build Coastguard Worker
203*6dbdd20aSAndroid Build Coastguard Worker template <typename MessageType>
WriteProto()204*6dbdd20aSAndroid Build Coastguard Worker TracedProto<MessageType> TracedValue::WriteProto() && {
205*6dbdd20aSAndroid Build Coastguard Worker return TracedProto<MessageType>(
206*6dbdd20aSAndroid Build Coastguard Worker static_cast<MessageType*>(WriteProtoInternal(MessageType::GetName())),
207*6dbdd20aSAndroid Build Coastguard Worker event_context_);
208*6dbdd20aSAndroid Build Coastguard Worker }
209*6dbdd20aSAndroid Build Coastguard Worker
210*6dbdd20aSAndroid Build Coastguard Worker class PERFETTO_EXPORT_COMPONENT TracedArray {
211*6dbdd20aSAndroid Build Coastguard Worker public:
212*6dbdd20aSAndroid Build Coastguard Worker // implicit
213*6dbdd20aSAndroid Build Coastguard Worker TracedArray(TracedValue);
214*6dbdd20aSAndroid Build Coastguard Worker
215*6dbdd20aSAndroid Build Coastguard Worker TracedArray(const TracedArray&) = delete;
216*6dbdd20aSAndroid Build Coastguard Worker TracedArray& operator=(const TracedArray&) = delete;
217*6dbdd20aSAndroid Build Coastguard Worker TracedArray& operator=(TracedArray&&) = delete;
218*6dbdd20aSAndroid Build Coastguard Worker TracedArray(TracedArray&&) = default;
219*6dbdd20aSAndroid Build Coastguard Worker ~TracedArray() = default;
220*6dbdd20aSAndroid Build Coastguard Worker
221*6dbdd20aSAndroid Build Coastguard Worker TracedValue AppendItem();
222*6dbdd20aSAndroid Build Coastguard Worker
223*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
Append(T && value)224*6dbdd20aSAndroid Build Coastguard Worker void Append(T&& value) {
225*6dbdd20aSAndroid Build Coastguard Worker WriteIntoTracedValue(AppendItem(), std::forward<T>(value));
226*6dbdd20aSAndroid Build Coastguard Worker }
227*6dbdd20aSAndroid Build Coastguard Worker
228*6dbdd20aSAndroid Build Coastguard Worker TracedDictionary AppendDictionary() PERFETTO_WARN_UNUSED_RESULT;
229*6dbdd20aSAndroid Build Coastguard Worker TracedArray AppendArray();
230*6dbdd20aSAndroid Build Coastguard Worker
231*6dbdd20aSAndroid Build Coastguard Worker private:
232*6dbdd20aSAndroid Build Coastguard Worker friend class TracedValue;
233*6dbdd20aSAndroid Build Coastguard Worker
TracedArray(protos::pbzero::DebugAnnotation * annotation,EventContext * event_context,internal::CheckedScope * parent_scope)234*6dbdd20aSAndroid Build Coastguard Worker inline TracedArray(protos::pbzero::DebugAnnotation* annotation,
235*6dbdd20aSAndroid Build Coastguard Worker EventContext* event_context,
236*6dbdd20aSAndroid Build Coastguard Worker internal::CheckedScope* parent_scope)
237*6dbdd20aSAndroid Build Coastguard Worker : annotation_(annotation),
238*6dbdd20aSAndroid Build Coastguard Worker event_context_(event_context),
239*6dbdd20aSAndroid Build Coastguard Worker checked_scope_(parent_scope) {}
240*6dbdd20aSAndroid Build Coastguard Worker
241*6dbdd20aSAndroid Build Coastguard Worker protos::pbzero::DebugAnnotation* annotation_;
242*6dbdd20aSAndroid Build Coastguard Worker EventContext* const event_context_;
243*6dbdd20aSAndroid Build Coastguard Worker
244*6dbdd20aSAndroid Build Coastguard Worker internal::CheckedScope checked_scope_;
245*6dbdd20aSAndroid Build Coastguard Worker };
246*6dbdd20aSAndroid Build Coastguard Worker
247*6dbdd20aSAndroid Build Coastguard Worker class PERFETTO_EXPORT_COMPONENT TracedDictionary {
248*6dbdd20aSAndroid Build Coastguard Worker public:
249*6dbdd20aSAndroid Build Coastguard Worker // implicit
250*6dbdd20aSAndroid Build Coastguard Worker TracedDictionary(TracedValue);
251*6dbdd20aSAndroid Build Coastguard Worker
252*6dbdd20aSAndroid Build Coastguard Worker TracedDictionary(const TracedDictionary&) = delete;
253*6dbdd20aSAndroid Build Coastguard Worker TracedDictionary& operator=(const TracedDictionary&) = delete;
254*6dbdd20aSAndroid Build Coastguard Worker TracedDictionary& operator=(TracedDictionary&&) = delete;
255*6dbdd20aSAndroid Build Coastguard Worker TracedDictionary(TracedDictionary&&) = default;
256*6dbdd20aSAndroid Build Coastguard Worker ~TracedDictionary() = default;
257*6dbdd20aSAndroid Build Coastguard Worker
258*6dbdd20aSAndroid Build Coastguard Worker // There are two paths for writing dictionary keys: fast path for writing
259*6dbdd20aSAndroid Build Coastguard Worker // compile-time const, whose pointer is remains valid during the entire
260*6dbdd20aSAndroid Build Coastguard Worker // runtime of the program and the slow path for dynamic strings, which need to
261*6dbdd20aSAndroid Build Coastguard Worker // be copied.
262*6dbdd20aSAndroid Build Coastguard Worker // In the most common case, a string literal can be passed to `Add`/`AddItem`.
263*6dbdd20aSAndroid Build Coastguard Worker // In other cases, either StaticString or DynamicString declarations are
264*6dbdd20aSAndroid Build Coastguard Worker // needed.
265*6dbdd20aSAndroid Build Coastguard Worker
266*6dbdd20aSAndroid Build Coastguard Worker TracedValue AddItem(StaticString key);
267*6dbdd20aSAndroid Build Coastguard Worker TracedValue AddItem(DynamicString key);
268*6dbdd20aSAndroid Build Coastguard Worker
269*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
Add(StaticString key,T && value)270*6dbdd20aSAndroid Build Coastguard Worker void Add(StaticString key, T&& value) {
271*6dbdd20aSAndroid Build Coastguard Worker WriteIntoTracedValue(AddItem(key), std::forward<T>(value));
272*6dbdd20aSAndroid Build Coastguard Worker }
273*6dbdd20aSAndroid Build Coastguard Worker
274*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
Add(DynamicString key,T && value)275*6dbdd20aSAndroid Build Coastguard Worker void Add(DynamicString key, T&& value) {
276*6dbdd20aSAndroid Build Coastguard Worker WriteIntoTracedValue(AddItem(key), std::forward<T>(value));
277*6dbdd20aSAndroid Build Coastguard Worker }
278*6dbdd20aSAndroid Build Coastguard Worker
279*6dbdd20aSAndroid Build Coastguard Worker TracedDictionary AddDictionary(StaticString key);
280*6dbdd20aSAndroid Build Coastguard Worker TracedDictionary AddDictionary(DynamicString key);
281*6dbdd20aSAndroid Build Coastguard Worker TracedArray AddArray(StaticString key);
282*6dbdd20aSAndroid Build Coastguard Worker TracedArray AddArray(DynamicString key);
283*6dbdd20aSAndroid Build Coastguard Worker
284*6dbdd20aSAndroid Build Coastguard Worker private:
285*6dbdd20aSAndroid Build Coastguard Worker friend class TracedValue;
286*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
287*6dbdd20aSAndroid Build Coastguard Worker friend class TracedProto;
288*6dbdd20aSAndroid Build Coastguard Worker
289*6dbdd20aSAndroid Build Coastguard Worker // Create a |TracedDictionary| which will populate the given field of the
290*6dbdd20aSAndroid Build Coastguard Worker // given |message|.
291*6dbdd20aSAndroid Build Coastguard Worker template <typename MessageType, typename FieldMetadata>
TracedDictionary(MessageType * message,FieldMetadata,EventContext * event_context,internal::CheckedScope * parent_scope)292*6dbdd20aSAndroid Build Coastguard Worker inline TracedDictionary(MessageType* message,
293*6dbdd20aSAndroid Build Coastguard Worker FieldMetadata,
294*6dbdd20aSAndroid Build Coastguard Worker EventContext* event_context,
295*6dbdd20aSAndroid Build Coastguard Worker internal::CheckedScope* parent_scope)
296*6dbdd20aSAndroid Build Coastguard Worker : message_(message),
297*6dbdd20aSAndroid Build Coastguard Worker field_id_(FieldMetadata::kFieldId),
298*6dbdd20aSAndroid Build Coastguard Worker event_context_(event_context),
299*6dbdd20aSAndroid Build Coastguard Worker checked_scope_(parent_scope) {
300*6dbdd20aSAndroid Build Coastguard Worker static_assert(std::is_base_of<protozero::Message, MessageType>::value,
301*6dbdd20aSAndroid Build Coastguard Worker "Message should be a subclass of protozero::Message");
302*6dbdd20aSAndroid Build Coastguard Worker static_assert(std::is_base_of<protozero::proto_utils::FieldMetadataBase,
303*6dbdd20aSAndroid Build Coastguard Worker FieldMetadata>::value,
304*6dbdd20aSAndroid Build Coastguard Worker "FieldMetadata should be a subclass of FieldMetadataBase");
305*6dbdd20aSAndroid Build Coastguard Worker static_assert(
306*6dbdd20aSAndroid Build Coastguard Worker std::is_same<typename FieldMetadata::message_type, MessageType>::value,
307*6dbdd20aSAndroid Build Coastguard Worker "Field does not belong to this message");
308*6dbdd20aSAndroid Build Coastguard Worker static_assert(
309*6dbdd20aSAndroid Build Coastguard Worker std::is_same<typename FieldMetadata::cpp_field_type,
310*6dbdd20aSAndroid Build Coastguard Worker ::perfetto::protos::pbzero::DebugAnnotation>::value,
311*6dbdd20aSAndroid Build Coastguard Worker "Field should be of DebugAnnotation type");
312*6dbdd20aSAndroid Build Coastguard Worker static_assert(
313*6dbdd20aSAndroid Build Coastguard Worker FieldMetadata::kRepetitionType ==
314*6dbdd20aSAndroid Build Coastguard Worker protozero::proto_utils::RepetitionType::kRepeatedNotPacked,
315*6dbdd20aSAndroid Build Coastguard Worker "Field should be non-packed repeated");
316*6dbdd20aSAndroid Build Coastguard Worker }
317*6dbdd20aSAndroid Build Coastguard Worker
318*6dbdd20aSAndroid Build Coastguard Worker protozero::Message* const message_;
319*6dbdd20aSAndroid Build Coastguard Worker const uint32_t field_id_;
320*6dbdd20aSAndroid Build Coastguard Worker EventContext* event_context_;
321*6dbdd20aSAndroid Build Coastguard Worker
322*6dbdd20aSAndroid Build Coastguard Worker internal::CheckedScope checked_scope_;
323*6dbdd20aSAndroid Build Coastguard Worker };
324*6dbdd20aSAndroid Build Coastguard Worker
325*6dbdd20aSAndroid Build Coastguard Worker namespace internal {
326*6dbdd20aSAndroid Build Coastguard Worker
327*6dbdd20aSAndroid Build Coastguard Worker // SFINAE helpers for finding a right overload to convert a given class to
328*6dbdd20aSAndroid Build Coastguard Worker // trace-friendly form, ordered from most to least preferred.
329*6dbdd20aSAndroid Build Coastguard Worker
330*6dbdd20aSAndroid Build Coastguard Worker constexpr int kMaxWriteImplPriority = 4;
331*6dbdd20aSAndroid Build Coastguard Worker
332*6dbdd20aSAndroid Build Coastguard Worker // If T has WriteIntoTracedValue member function, call it.
333*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
334*6dbdd20aSAndroid Build Coastguard Worker decltype(std::declval<T>().WriteIntoTracedValue(std::declval<TracedValue>()),
335*6dbdd20aSAndroid Build Coastguard Worker void())
WriteImpl(base::priority_tag<4>,TracedValue context,T && value)336*6dbdd20aSAndroid Build Coastguard Worker WriteImpl(base::priority_tag<4>, TracedValue context, T&& value) {
337*6dbdd20aSAndroid Build Coastguard Worker value.WriteIntoTracedValue(std::move(context));
338*6dbdd20aSAndroid Build Coastguard Worker }
339*6dbdd20aSAndroid Build Coastguard Worker
340*6dbdd20aSAndroid Build Coastguard Worker // If T has WriteIntoTrace member function, call it.
341*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
342*6dbdd20aSAndroid Build Coastguard Worker decltype(std::declval<T>().WriteIntoTrace(std::declval<TracedValue>()), void())
WriteImpl(base::priority_tag<4>,TracedValue context,T && value)343*6dbdd20aSAndroid Build Coastguard Worker WriteImpl(base::priority_tag<4>, TracedValue context, T&& value) {
344*6dbdd20aSAndroid Build Coastguard Worker value.WriteIntoTrace(std::move(context));
345*6dbdd20aSAndroid Build Coastguard Worker }
346*6dbdd20aSAndroid Build Coastguard Worker
347*6dbdd20aSAndroid Build Coastguard Worker // If perfetto::TraceFormatTraits<T>::WriteIntoTracedValue(TracedValue, const
348*6dbdd20aSAndroid Build Coastguard Worker // T&) is available, use it.
349*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
decltype(TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTracedValue (std::declval<TracedValue> (),std::declval<T> ()),void ())350*6dbdd20aSAndroid Build Coastguard Worker decltype(TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTracedValue(
351*6dbdd20aSAndroid Build Coastguard Worker std::declval<TracedValue>(),
352*6dbdd20aSAndroid Build Coastguard Worker std::declval<T>()),
353*6dbdd20aSAndroid Build Coastguard Worker void())
354*6dbdd20aSAndroid Build Coastguard Worker WriteImpl(base::priority_tag<3>, TracedValue context, T&& value) {
355*6dbdd20aSAndroid Build Coastguard Worker TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTracedValue(
356*6dbdd20aSAndroid Build Coastguard Worker std::move(context), std::forward<T>(value));
357*6dbdd20aSAndroid Build Coastguard Worker }
358*6dbdd20aSAndroid Build Coastguard Worker
359*6dbdd20aSAndroid Build Coastguard Worker // If perfetto::TraceFormatTraits<T>::WriteIntoTrace(TracedValue, const T&)
360*6dbdd20aSAndroid Build Coastguard Worker // is available, use it.
361*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
decltype(TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTrace (std::declval<TracedValue> (),std::declval<T> ()),void ())362*6dbdd20aSAndroid Build Coastguard Worker decltype(TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTrace(
363*6dbdd20aSAndroid Build Coastguard Worker std::declval<TracedValue>(),
364*6dbdd20aSAndroid Build Coastguard Worker std::declval<T>()),
365*6dbdd20aSAndroid Build Coastguard Worker void())
366*6dbdd20aSAndroid Build Coastguard Worker WriteImpl(base::priority_tag<3>, TracedValue context, T&& value) {
367*6dbdd20aSAndroid Build Coastguard Worker TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTrace(
368*6dbdd20aSAndroid Build Coastguard Worker std::move(context), std::forward<T>(value));
369*6dbdd20aSAndroid Build Coastguard Worker }
370*6dbdd20aSAndroid Build Coastguard Worker
371*6dbdd20aSAndroid Build Coastguard Worker // If T has operator(), which takes TracedValue, use it.
372*6dbdd20aSAndroid Build Coastguard Worker // Very useful for lambda resolutions.
373*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
decltype(std::declval<T> ()(std::declval<TracedValue> ()),void ())374*6dbdd20aSAndroid Build Coastguard Worker decltype(std::declval<T>()(std::declval<TracedValue>()), void())
375*6dbdd20aSAndroid Build Coastguard Worker WriteImpl(base::priority_tag<2>, TracedValue context, T&& value) {
376*6dbdd20aSAndroid Build Coastguard Worker std::forward<T>(value)(std::move(context));
377*6dbdd20aSAndroid Build Coastguard Worker }
378*6dbdd20aSAndroid Build Coastguard Worker
379*6dbdd20aSAndroid Build Coastguard Worker // If T is a container and its elements have tracing support, use it.
380*6dbdd20aSAndroid Build Coastguard Worker //
381*6dbdd20aSAndroid Build Coastguard Worker // Note: a reference to T should be passed to std::begin, otherwise
382*6dbdd20aSAndroid Build Coastguard Worker // for non-reference types const T& will be passed to std::begin, losing
383*6dbdd20aSAndroid Build Coastguard Worker // support for non-const WriteIntoTracedValue methods.
384*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
385*6dbdd20aSAndroid Build Coastguard Worker typename check_traced_value_support<
386*6dbdd20aSAndroid Build Coastguard Worker decltype(*std::begin(std::declval<T&>()))>::type
WriteImpl(base::priority_tag<1>,TracedValue context,T && value)387*6dbdd20aSAndroid Build Coastguard Worker WriteImpl(base::priority_tag<1>, TracedValue context, T&& value) {
388*6dbdd20aSAndroid Build Coastguard Worker auto array = std::move(context).WriteArray();
389*6dbdd20aSAndroid Build Coastguard Worker for (auto&& item : value) {
390*6dbdd20aSAndroid Build Coastguard Worker array.Append(item);
391*6dbdd20aSAndroid Build Coastguard Worker }
392*6dbdd20aSAndroid Build Coastguard Worker }
393*6dbdd20aSAndroid Build Coastguard Worker
394*6dbdd20aSAndroid Build Coastguard Worker // std::underlying_type can't be used with non-enum types, so we need this
395*6dbdd20aSAndroid Build Coastguard Worker // indirection.
396*6dbdd20aSAndroid Build Coastguard Worker template <typename T, bool = std::is_enum<T>::value>
397*6dbdd20aSAndroid Build Coastguard Worker struct safe_underlying_type {
398*6dbdd20aSAndroid Build Coastguard Worker using type = typename std::underlying_type<T>::type;
399*6dbdd20aSAndroid Build Coastguard Worker };
400*6dbdd20aSAndroid Build Coastguard Worker
401*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
402*6dbdd20aSAndroid Build Coastguard Worker struct safe_underlying_type<T, false> {
403*6dbdd20aSAndroid Build Coastguard Worker using type = T;
404*6dbdd20aSAndroid Build Coastguard Worker };
405*6dbdd20aSAndroid Build Coastguard Worker
406*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
407*6dbdd20aSAndroid Build Coastguard Worker struct is_incomplete_type {
408*6dbdd20aSAndroid Build Coastguard Worker static constexpr bool value = sizeof(T) != 0;
409*6dbdd20aSAndroid Build Coastguard Worker };
410*6dbdd20aSAndroid Build Coastguard Worker
411*6dbdd20aSAndroid Build Coastguard Worker // sizeof is not available for const char[], but it's still not considered to be
412*6dbdd20aSAndroid Build Coastguard Worker // an incomplete type for our purposes as the size can be determined at runtime
413*6dbdd20aSAndroid Build Coastguard Worker // due to strings being null-terminated.
414*6dbdd20aSAndroid Build Coastguard Worker template <>
415*6dbdd20aSAndroid Build Coastguard Worker struct is_incomplete_type<const char[]> {
416*6dbdd20aSAndroid Build Coastguard Worker static constexpr bool value = true;
417*6dbdd20aSAndroid Build Coastguard Worker };
418*6dbdd20aSAndroid Build Coastguard Worker
419*6dbdd20aSAndroid Build Coastguard Worker } // namespace internal
420*6dbdd20aSAndroid Build Coastguard Worker
421*6dbdd20aSAndroid Build Coastguard Worker // Helper template to determine if a given type can be passed to
422*6dbdd20aSAndroid Build Coastguard Worker // perfetto::WriteIntoTracedValue. These templates will fail to resolve if the
423*6dbdd20aSAndroid Build Coastguard Worker // class does not have it support, so they are useful in SFINAE and in producing
424*6dbdd20aSAndroid Build Coastguard Worker // helpful compiler results.
425*6dbdd20aSAndroid Build Coastguard Worker template <typename T, class Result = void>
426*6dbdd20aSAndroid Build Coastguard Worker using check_traced_value_support_t = decltype(
427*6dbdd20aSAndroid Build Coastguard Worker internal::WriteImpl(
428*6dbdd20aSAndroid Build Coastguard Worker std::declval<base::priority_tag<internal::kMaxWriteImplPriority>>(),
429*6dbdd20aSAndroid Build Coastguard Worker std::declval<TracedValue>(),
430*6dbdd20aSAndroid Build Coastguard Worker std::declval<T>()),
431*6dbdd20aSAndroid Build Coastguard Worker std::declval<Result>());
432*6dbdd20aSAndroid Build Coastguard Worker
433*6dbdd20aSAndroid Build Coastguard Worker // check_traced_value_support<T, V>::type is defined (and equal to V) iff T
434*6dbdd20aSAndroid Build Coastguard Worker // supports being passed to WriteIntoTracedValue. See the comment in
435*6dbdd20aSAndroid Build Coastguard Worker // traced_value_forward.h for more details.
436*6dbdd20aSAndroid Build Coastguard Worker template <typename T, class Result>
437*6dbdd20aSAndroid Build Coastguard Worker struct check_traced_value_support<T,
438*6dbdd20aSAndroid Build Coastguard Worker Result,
439*6dbdd20aSAndroid Build Coastguard Worker check_traced_value_support_t<T, Result>> {
440*6dbdd20aSAndroid Build Coastguard Worker static_assert(
441*6dbdd20aSAndroid Build Coastguard Worker internal::is_incomplete_type<T>::value,
442*6dbdd20aSAndroid Build Coastguard Worker "perfetto::TracedValue should not be used with incomplete types");
443*6dbdd20aSAndroid Build Coastguard Worker
444*6dbdd20aSAndroid Build Coastguard Worker static constexpr bool value = true;
445*6dbdd20aSAndroid Build Coastguard Worker using type = Result;
446*6dbdd20aSAndroid Build Coastguard Worker };
447*6dbdd20aSAndroid Build Coastguard Worker
448*6dbdd20aSAndroid Build Coastguard Worker namespace internal {
449*6dbdd20aSAndroid Build Coastguard Worker
450*6dbdd20aSAndroid Build Coastguard Worker // Helper class to check if a given type can be passed to
451*6dbdd20aSAndroid Build Coastguard Worker // perfetto::WriteIntoTracedValue. This template will always resolve (with
452*6dbdd20aSAndroid Build Coastguard Worker // |value| being set to either true or false depending on presence of the
453*6dbdd20aSAndroid Build Coastguard Worker // support, so this macro is useful in the situation when you want to e.g. OR
454*6dbdd20aSAndroid Build Coastguard Worker // the result with some other conditions.
455*6dbdd20aSAndroid Build Coastguard Worker //
456*6dbdd20aSAndroid Build Coastguard Worker // In this case, compiler will not give you the full deduction chain, so, for
457*6dbdd20aSAndroid Build Coastguard Worker // example, use check_traced_value_support for writing positive static_asserts
458*6dbdd20aSAndroid Build Coastguard Worker // and has_traced_value_support for writing negative.
459*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
460*6dbdd20aSAndroid Build Coastguard Worker class has_traced_value_support {
461*6dbdd20aSAndroid Build Coastguard Worker using Yes = char[1];
462*6dbdd20aSAndroid Build Coastguard Worker using No = char[2];
463*6dbdd20aSAndroid Build Coastguard Worker
464*6dbdd20aSAndroid Build Coastguard Worker template <typename V>
465*6dbdd20aSAndroid Build Coastguard Worker static Yes& check_support(check_traced_value_support_t<V, int>);
466*6dbdd20aSAndroid Build Coastguard Worker template <typename V>
467*6dbdd20aSAndroid Build Coastguard Worker static No& check_support(...);
468*6dbdd20aSAndroid Build Coastguard Worker
469*6dbdd20aSAndroid Build Coastguard Worker public:
470*6dbdd20aSAndroid Build Coastguard Worker static constexpr bool value = sizeof(Yes) == sizeof(check_support<T>(0));
471*6dbdd20aSAndroid Build Coastguard Worker };
472*6dbdd20aSAndroid Build Coastguard Worker
473*6dbdd20aSAndroid Build Coastguard Worker } // namespace internal
474*6dbdd20aSAndroid Build Coastguard Worker
475*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
476*6dbdd20aSAndroid Build Coastguard Worker void WriteIntoTracedValue(TracedValue context, T&& value) {
477*6dbdd20aSAndroid Build Coastguard Worker // TODO(altimin): Add a URL to documentation and a list of common failure
478*6dbdd20aSAndroid Build Coastguard Worker // patterns.
479*6dbdd20aSAndroid Build Coastguard Worker static_assert(
480*6dbdd20aSAndroid Build Coastguard Worker internal::has_traced_value_support<T>::value,
481*6dbdd20aSAndroid Build Coastguard Worker "The provided type (passed to TRACE_EVENT argument / TracedArray::Append "
482*6dbdd20aSAndroid Build Coastguard Worker "/ TracedDictionary::Add) does not support being written in a trace "
483*6dbdd20aSAndroid Build Coastguard Worker "format. Please see the comment in traced_value.h for more details.");
484*6dbdd20aSAndroid Build Coastguard Worker
485*6dbdd20aSAndroid Build Coastguard Worker // Should be kept in sync with check_traced_value_support_t!
486*6dbdd20aSAndroid Build Coastguard Worker internal::WriteImpl(base::priority_tag<internal::kMaxWriteImplPriority>(),
487*6dbdd20aSAndroid Build Coastguard Worker std::move(context), std::forward<T>(value));
488*6dbdd20aSAndroid Build Coastguard Worker }
489*6dbdd20aSAndroid Build Coastguard Worker
490*6dbdd20aSAndroid Build Coastguard Worker // Helpers to write a given value into TracedValue even if the given type
491*6dbdd20aSAndroid Build Coastguard Worker // doesn't support conversion (in which case the provided fallback should be
492*6dbdd20aSAndroid Build Coastguard Worker // used). Useful for automatically generating conversions for autogenerated
493*6dbdd20aSAndroid Build Coastguard Worker // code, but otherwise shouldn't be used as non-autogenerated code is expected
494*6dbdd20aSAndroid Build Coastguard Worker // to define WriteIntoTracedValue convertor.
495*6dbdd20aSAndroid Build Coastguard Worker // See WriteWithFallback test in traced_value_unittest.cc for a concrete
496*6dbdd20aSAndroid Build Coastguard Worker // example.
497*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
498*6dbdd20aSAndroid Build Coastguard Worker typename std::enable_if<internal::has_traced_value_support<T>::value>::type
499*6dbdd20aSAndroid Build Coastguard Worker WriteIntoTracedValueWithFallback(TracedValue context,
500*6dbdd20aSAndroid Build Coastguard Worker T&& value,
501*6dbdd20aSAndroid Build Coastguard Worker const std::string&) {
502*6dbdd20aSAndroid Build Coastguard Worker WriteIntoTracedValue(std::move(context), std::forward<T>(value));
503*6dbdd20aSAndroid Build Coastguard Worker }
504*6dbdd20aSAndroid Build Coastguard Worker
505*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
506*6dbdd20aSAndroid Build Coastguard Worker typename std::enable_if<!internal::has_traced_value_support<T>::value>::type
507*6dbdd20aSAndroid Build Coastguard Worker WriteIntoTracedValueWithFallback(TracedValue context,
508*6dbdd20aSAndroid Build Coastguard Worker T&&,
509*6dbdd20aSAndroid Build Coastguard Worker const std::string& fallback) {
510*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WriteString(fallback);
511*6dbdd20aSAndroid Build Coastguard Worker }
512*6dbdd20aSAndroid Build Coastguard Worker
513*6dbdd20aSAndroid Build Coastguard Worker // TraceFormatTraits implementations for primitive types.
514*6dbdd20aSAndroid Build Coastguard Worker
515*6dbdd20aSAndroid Build Coastguard Worker // Specialisation for signed integer types (note: it excludes enums, which have
516*6dbdd20aSAndroid Build Coastguard Worker // their own explicit specialisation).
517*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
518*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<
519*6dbdd20aSAndroid Build Coastguard Worker T,
520*6dbdd20aSAndroid Build Coastguard Worker typename std::enable_if<std::is_integral<T>::value &&
521*6dbdd20aSAndroid Build Coastguard Worker !std::is_same<T, bool>::value &&
522*6dbdd20aSAndroid Build Coastguard Worker std::is_signed<T>::value>::type> {
523*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context, T value) {
524*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WriteInt64(value);
525*6dbdd20aSAndroid Build Coastguard Worker }
526*6dbdd20aSAndroid Build Coastguard Worker };
527*6dbdd20aSAndroid Build Coastguard Worker
528*6dbdd20aSAndroid Build Coastguard Worker // Specialisation for unsigned integer types (note: it excludes enums, which
529*6dbdd20aSAndroid Build Coastguard Worker // have their own explicit specialisation).
530*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
531*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<
532*6dbdd20aSAndroid Build Coastguard Worker T,
533*6dbdd20aSAndroid Build Coastguard Worker typename std::enable_if<std::is_integral<T>::value &&
534*6dbdd20aSAndroid Build Coastguard Worker !std::is_same<T, bool>::value &&
535*6dbdd20aSAndroid Build Coastguard Worker std::is_unsigned<T>::value>::type> {
536*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context, T value) {
537*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WriteUInt64(value);
538*6dbdd20aSAndroid Build Coastguard Worker }
539*6dbdd20aSAndroid Build Coastguard Worker };
540*6dbdd20aSAndroid Build Coastguard Worker
541*6dbdd20aSAndroid Build Coastguard Worker // Specialisation for bools.
542*6dbdd20aSAndroid Build Coastguard Worker template <>
543*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<bool> {
544*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context, bool value) {
545*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WriteBoolean(value);
546*6dbdd20aSAndroid Build Coastguard Worker }
547*6dbdd20aSAndroid Build Coastguard Worker };
548*6dbdd20aSAndroid Build Coastguard Worker
549*6dbdd20aSAndroid Build Coastguard Worker // Specialisation for floating point values.
550*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
551*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<
552*6dbdd20aSAndroid Build Coastguard Worker T,
553*6dbdd20aSAndroid Build Coastguard Worker typename std::enable_if<std::is_floating_point<T>::value>::type> {
554*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context, T value) {
555*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WriteDouble(static_cast<double>(value));
556*6dbdd20aSAndroid Build Coastguard Worker }
557*6dbdd20aSAndroid Build Coastguard Worker };
558*6dbdd20aSAndroid Build Coastguard Worker
559*6dbdd20aSAndroid Build Coastguard Worker // Specialisation for signed enums.
560*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
561*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<
562*6dbdd20aSAndroid Build Coastguard Worker T,
563*6dbdd20aSAndroid Build Coastguard Worker typename std::enable_if<
564*6dbdd20aSAndroid Build Coastguard Worker std::is_enum<T>::value &&
565*6dbdd20aSAndroid Build Coastguard Worker std::is_signed<
566*6dbdd20aSAndroid Build Coastguard Worker typename internal::safe_underlying_type<T>::type>::value>::type> {
567*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context, T value) {
568*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WriteInt64(static_cast<int64_t>(value));
569*6dbdd20aSAndroid Build Coastguard Worker }
570*6dbdd20aSAndroid Build Coastguard Worker };
571*6dbdd20aSAndroid Build Coastguard Worker
572*6dbdd20aSAndroid Build Coastguard Worker // Specialisation for unsigned enums.
573*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
574*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<
575*6dbdd20aSAndroid Build Coastguard Worker T,
576*6dbdd20aSAndroid Build Coastguard Worker typename std::enable_if<
577*6dbdd20aSAndroid Build Coastguard Worker std::is_enum<T>::value &&
578*6dbdd20aSAndroid Build Coastguard Worker std::is_unsigned<
579*6dbdd20aSAndroid Build Coastguard Worker typename internal::safe_underlying_type<T>::type>::value>::type> {
580*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context, T value) {
581*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WriteUInt64(static_cast<uint64_t>(value));
582*6dbdd20aSAndroid Build Coastguard Worker }
583*6dbdd20aSAndroid Build Coastguard Worker };
584*6dbdd20aSAndroid Build Coastguard Worker
585*6dbdd20aSAndroid Build Coastguard Worker // Specialisations for C-style strings.
586*6dbdd20aSAndroid Build Coastguard Worker template <>
587*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<const char*> {
588*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context, const char* value) {
589*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WriteString(value);
590*6dbdd20aSAndroid Build Coastguard Worker }
591*6dbdd20aSAndroid Build Coastguard Worker };
592*6dbdd20aSAndroid Build Coastguard Worker
593*6dbdd20aSAndroid Build Coastguard Worker template <>
594*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<char[]> {
595*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context, const char value[]) {
596*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WriteString(value);
597*6dbdd20aSAndroid Build Coastguard Worker }
598*6dbdd20aSAndroid Build Coastguard Worker };
599*6dbdd20aSAndroid Build Coastguard Worker
600*6dbdd20aSAndroid Build Coastguard Worker template <size_t N>
601*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<char[N]> {
602*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context, const char value[N]) {
603*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WriteString(value);
604*6dbdd20aSAndroid Build Coastguard Worker }
605*6dbdd20aSAndroid Build Coastguard Worker };
606*6dbdd20aSAndroid Build Coastguard Worker
607*6dbdd20aSAndroid Build Coastguard Worker // Specialization for Perfetto strings.
608*6dbdd20aSAndroid Build Coastguard Worker template <>
609*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<perfetto::StaticString> {
610*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context,
611*6dbdd20aSAndroid Build Coastguard Worker perfetto::StaticString str) {
612*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WriteString(str.value);
613*6dbdd20aSAndroid Build Coastguard Worker }
614*6dbdd20aSAndroid Build Coastguard Worker };
615*6dbdd20aSAndroid Build Coastguard Worker
616*6dbdd20aSAndroid Build Coastguard Worker template <>
617*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<perfetto::DynamicString> {
618*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context,
619*6dbdd20aSAndroid Build Coastguard Worker perfetto::DynamicString str) {
620*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WriteString(str.value, str.length);
621*6dbdd20aSAndroid Build Coastguard Worker }
622*6dbdd20aSAndroid Build Coastguard Worker };
623*6dbdd20aSAndroid Build Coastguard Worker
624*6dbdd20aSAndroid Build Coastguard Worker // Specialisation for C++ strings.
625*6dbdd20aSAndroid Build Coastguard Worker template <>
626*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<std::string> {
627*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context,
628*6dbdd20aSAndroid Build Coastguard Worker const std::string& value) {
629*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WriteString(value);
630*6dbdd20aSAndroid Build Coastguard Worker }
631*6dbdd20aSAndroid Build Coastguard Worker };
632*6dbdd20aSAndroid Build Coastguard Worker
633*6dbdd20aSAndroid Build Coastguard Worker // Specialisation for C++ string_views.
634*6dbdd20aSAndroid Build Coastguard Worker template <>
635*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<std::string_view> {
636*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context,
637*6dbdd20aSAndroid Build Coastguard Worker std::string_view value) {
638*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WriteString(value);
639*6dbdd20aSAndroid Build Coastguard Worker }
640*6dbdd20aSAndroid Build Coastguard Worker };
641*6dbdd20aSAndroid Build Coastguard Worker
642*6dbdd20aSAndroid Build Coastguard Worker // Specialisation for (const) void*, which writes the pointer value.
643*6dbdd20aSAndroid Build Coastguard Worker template <>
644*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<void*> {
645*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context, void* value) {
646*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WritePointer(value);
647*6dbdd20aSAndroid Build Coastguard Worker }
648*6dbdd20aSAndroid Build Coastguard Worker };
649*6dbdd20aSAndroid Build Coastguard Worker
650*6dbdd20aSAndroid Build Coastguard Worker template <>
651*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<const void*> {
652*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context, const void* value) {
653*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WritePointer(value);
654*6dbdd20aSAndroid Build Coastguard Worker }
655*6dbdd20aSAndroid Build Coastguard Worker };
656*6dbdd20aSAndroid Build Coastguard Worker
657*6dbdd20aSAndroid Build Coastguard Worker // Specialisation for std::unique_ptr<>, which writes either nullptr or the
658*6dbdd20aSAndroid Build Coastguard Worker // object it points to.
659*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
660*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<std::unique_ptr<T>, check_traced_value_support_t<T>> {
661*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context,
662*6dbdd20aSAndroid Build Coastguard Worker const std::unique_ptr<T>& value) {
663*6dbdd20aSAndroid Build Coastguard Worker ::perfetto::WriteIntoTracedValue(std::move(context), value.get());
664*6dbdd20aSAndroid Build Coastguard Worker }
665*6dbdd20aSAndroid Build Coastguard Worker
666*6dbdd20aSAndroid Build Coastguard Worker template <typename MessageType>
667*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedProto<MessageType> message,
668*6dbdd20aSAndroid Build Coastguard Worker const std::unique_ptr<T>& value) {
669*6dbdd20aSAndroid Build Coastguard Worker ::perfetto::WriteIntoTracedProto(std::move(message), value.get());
670*6dbdd20aSAndroid Build Coastguard Worker }
671*6dbdd20aSAndroid Build Coastguard Worker };
672*6dbdd20aSAndroid Build Coastguard Worker
673*6dbdd20aSAndroid Build Coastguard Worker // Specialisation for raw pointer, which writes either nullptr or the object it
674*6dbdd20aSAndroid Build Coastguard Worker // points to.
675*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
676*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<T*, check_traced_value_support_t<T>> {
677*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context, T* value) {
678*6dbdd20aSAndroid Build Coastguard Worker if (!value) {
679*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WritePointer(nullptr);
680*6dbdd20aSAndroid Build Coastguard Worker return;
681*6dbdd20aSAndroid Build Coastguard Worker }
682*6dbdd20aSAndroid Build Coastguard Worker ::perfetto::WriteIntoTracedValue(std::move(context), *value);
683*6dbdd20aSAndroid Build Coastguard Worker }
684*6dbdd20aSAndroid Build Coastguard Worker
685*6dbdd20aSAndroid Build Coastguard Worker template <typename MessageType>
686*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedProto<MessageType> message,
687*6dbdd20aSAndroid Build Coastguard Worker T* value) {
688*6dbdd20aSAndroid Build Coastguard Worker if (!value) {
689*6dbdd20aSAndroid Build Coastguard Worker // Start the message, but do not write anything. TraceProcessor will emit
690*6dbdd20aSAndroid Build Coastguard Worker // a NULL value.
691*6dbdd20aSAndroid Build Coastguard Worker return;
692*6dbdd20aSAndroid Build Coastguard Worker }
693*6dbdd20aSAndroid Build Coastguard Worker
694*6dbdd20aSAndroid Build Coastguard Worker ::perfetto::WriteIntoTracedProto(std::move(message), *value);
695*6dbdd20aSAndroid Build Coastguard Worker }
696*6dbdd20aSAndroid Build Coastguard Worker };
697*6dbdd20aSAndroid Build Coastguard Worker
698*6dbdd20aSAndroid Build Coastguard Worker // Specialisation for nullptr.
699*6dbdd20aSAndroid Build Coastguard Worker template <>
700*6dbdd20aSAndroid Build Coastguard Worker struct TraceFormatTraits<std::nullptr_t> {
701*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedValue context, std::nullptr_t) {
702*6dbdd20aSAndroid Build Coastguard Worker std::move(context).WritePointer(nullptr);
703*6dbdd20aSAndroid Build Coastguard Worker }
704*6dbdd20aSAndroid Build Coastguard Worker
705*6dbdd20aSAndroid Build Coastguard Worker template <typename MessageType>
706*6dbdd20aSAndroid Build Coastguard Worker inline static void WriteIntoTrace(TracedProto<MessageType>, std::nullptr_t) {
707*6dbdd20aSAndroid Build Coastguard Worker // Start the message, but do not write anything. TraceProcessor will emit a
708*6dbdd20aSAndroid Build Coastguard Worker // NULL value.
709*6dbdd20aSAndroid Build Coastguard Worker }
710*6dbdd20aSAndroid Build Coastguard Worker };
711*6dbdd20aSAndroid Build Coastguard Worker
712*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto
713*6dbdd20aSAndroid Build Coastguard Worker
714*6dbdd20aSAndroid Build Coastguard Worker #endif // INCLUDE_PERFETTO_TRACING_TRACED_VALUE_H_
715