trace_arguments.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. // Copyright 2018 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. #ifndef BASE_TRACE_EVENT_TRACE_ARGUMENTS_H_
  5. #define BASE_TRACE_EVENT_TRACE_ARGUMENTS_H_
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <algorithm>
  9. #include <memory>
  10. #include <string>
  11. #include "base/base_export.h"
  12. #include "base/macros.h"
  13. #include "base/trace_event/common/trace_event_common.h"
  14. // Trace macro can have one or two optional arguments, each one of them
  15. // identified by a name (a C string literal) and a value, which can be an
  16. // integer, enum, floating point, boolean, string pointer or reference, or
  17. // std::unique_ptr<ConvertableToTraceFormat> compatible values. Additionally,
  18. // custom data types need to be supported, like time values or WTF::CString.
  19. //
  20. // TraceArguments is a helper class used to store 0 to 2 named arguments
  21. // corresponding to an individual trace macro call. As efficiently as possible,
  22. // and with the minimal amount of generated machine code (since this affects
  23. // any TRACE macro call). Each argument has:
  24. //
  25. // - A name (C string literal, e.g "dumps")
  26. // - An 8-bit type value, corresponding to the TRACE_VALUE_TYPE_XXX macros.
  27. // - A value, stored in a TraceValue union
  28. //
  29. // IMPORTANT: For a TRACE_VALUE_TYPE_CONVERTABLE types, the TraceArguments
  30. // instance owns the pointed ConvertableToTraceFormat object, i.e. it will
  31. // delete it automatically on destruction.
  32. //
  33. // TraceArguments instances should be built using one of specialized
  34. // constructors declared below. One cannot modify an instance once it has
  35. // been built, except for move operations, Reset() and destruction. Examples:
  36. //
  37. // TraceArguments args; // No arguments.
  38. // // args.size() == 0
  39. //
  40. // TraceArguments("foo", 100);
  41. // // args.size() == 1
  42. // // args.types()[0] == TRACE_VALUE_TYPE_INT
  43. // // args.names()[0] == "foo"
  44. // // args.values()[0].as_int == 100
  45. //
  46. // TraceArguments("bar", 1ULL);
  47. // // args.size() == 1
  48. // // args.types()[0] == TRACE_VALUE_TYPE_UINT
  49. // // args.names()[0] == "bar"
  50. // // args.values()[0].as_uint == 100
  51. //
  52. // TraceArguments("foo", "Hello", "bar", "World");
  53. // // args.size() == 2
  54. // // args.types()[0] == TRACE_VALUE_TYPE_STRING
  55. // // args.types()[1] == TRACE_VALUE_TYPE_STRING
  56. // // args.names()[0] == "foo"
  57. // // args.names()[1] == "bar"
  58. // // args.values()[0].as_string == "Hello"
  59. // // args.values()[1].as_string == "World"
  60. //
  61. // std::string some_string = ...;
  62. // TraceArguments("str1", some_string);
  63. // // args.size() == 1
  64. // // args.types()[0] == TRACE_VALUE_TYPE_COPY_STRING
  65. // // args.names()[0] == "str1"
  66. // // args.values()[0].as_string == some_string.c_str()
  67. //
  68. // Note that TRACE_VALUE_TYPE_COPY_STRING corresponds to string pointers
  69. // that point to temporary values that may disappear soon. The
  70. // TraceArguments::CopyStringTo() method can be used to copy their content
  71. // into a StringStorage memory block, and update the |as_string| value pointers
  72. // to it to avoid keeping any dangling pointers. This is used by TraceEvent
  73. // to keep copies of such strings in the log after their initialization values
  74. // have disappeared.
  75. //
  76. // The TraceStringWithCopy helper class can be used to initialize a value
  77. // from a regular string pointer with TRACE_VALUE_TYPE_COPY_STRING too, as in:
  78. //
  79. // const char str[] = "....";
  80. // TraceArguments("foo", str, "bar", TraceStringWithCopy(str));
  81. // // args.size() == 2
  82. // // args.types()[0] == TRACE_VALUE_TYPE_STRING
  83. // // args.types()[1] == TRACE_VALUE_TYPE_COPY_STRING
  84. // // args.names()[0] == "foo"
  85. // // args.names()[1] == "bar"
  86. // // args.values()[0].as_string == str
  87. // // args.values()[1].as_string == str
  88. //
  89. // StringStorage storage;
  90. // args.CopyStringTo(&storage, false, nullptr, nullptr);
  91. // // args.size() == 2
  92. // // args.types()[0] == TRACE_VALUE_TYPE_STRING
  93. // // args.types()[1] == TRACE_VALUE_TYPE_COPY_STRING
  94. // // args.names()[0] == "foo"
  95. // // args.names()[1] == "bar"
  96. // // args.values()[0].as_string == str
  97. // // args.values()[1].as_string == Address inside |storage|.
  98. //
  99. // Initialization from a std::unique_ptr<ConvertableToTraceFormat>
  100. // is supported but will move ownership of the pointer objects to the
  101. // TraceArguments instance:
  102. //
  103. // class MyConvertableType :
  104. // public base::trace_event::AsConvertableToTraceFormat {
  105. // ...
  106. // };
  107. //
  108. // {
  109. // TraceArguments args("foo" , std::make_unique<MyConvertableType>(...));
  110. // // args.size() == 1
  111. // // args.values()[0].as_convertable == address of MyConvertable object.
  112. // } // Calls |args| destructor, which will delete the object too.
  113. //
  114. // Finally, it is possible to support initialization from custom values by
  115. // specializing the TraceValue::Helper<> template struct as described below.
  116. //
  117. // This is how values of custom types like WTF::CString can be passed directly
  118. // to trace macros.
  119. namespace base {
  120. class Time;
  121. class TimeTicks;
  122. class ThreadTicks;
  123. namespace trace_event {
  124. class TraceEventMemoryOverhead;
  125. // For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided
  126. // class must implement this interface. Note that unlike other values,
  127. // these objects will be owned by the TraceArguments instance that points
  128. // to them.
  129. class BASE_EXPORT ConvertableToTraceFormat {
  130. public:
  131. ConvertableToTraceFormat() = default;
  132. virtual ~ConvertableToTraceFormat() = default;
  133. // Append the class info to the provided |out| string. The appended
  134. // data must be a valid JSON object. Strings must be properly quoted, and
  135. // escaped. There is no processing applied to the content after it is
  136. // appended.
  137. virtual void AppendAsTraceFormat(std::string* out) const = 0;
  138. // Append the class info directly into the Perfetto-defined proto
  139. // format; this is attempted first and if this returns true,
  140. // AppendAsTraceFormat is not called. The ProtoAppender interface
  141. // acts as a bridge to avoid proto/Perfetto dependencies in base.
  142. class BASE_EXPORT ProtoAppender {
  143. public:
  144. virtual ~ProtoAppender() = default;
  145. virtual void AddBuffer(uint8_t* begin, uint8_t* end) = 0;
  146. // Copy all of the previous buffers registered with AddBuffer
  147. // into the proto, with the given |field_id|.
  148. virtual size_t Finalize(uint32_t field_id) = 0;
  149. };
  150. virtual bool AppendToProto(ProtoAppender* appender);
  151. virtual void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead);
  152. private:
  153. DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormat);
  154. };
  155. const int kTraceMaxNumArgs = 2;
  156. // A union used to hold the values of individual trace arguments.
  157. //
  158. // This is a POD union for performance reason. Initialization from an
  159. // explicit C++ trace argument should be performed with the Init()
  160. // templated method described below.
  161. //
  162. // Initialization from custom types is possible by implementing a custom
  163. // TraceValue::Helper<> instantiation as described below.
  164. //
  165. // IMPORTANT: Pointer storage inside a TraceUnion follows specific rules:
  166. //
  167. // - |as_pointer| is for raw pointers that should be treated as a simple
  168. // address and will never be dereferenced. Associated with the
  169. // TRACE_VALUE_TYPE_POINTER type.
  170. //
  171. // - |as_string| is for C-string pointers, associated with both
  172. // TRACE_VALUE_TYPE_STRING and TRACE_VALUE_TYPE_COPY_STRING. The former
  173. // indicates that the string pointer is persistent (e.g. a C string
  174. // literal), while the second indicates that the pointer belongs to a
  175. // temporary variable that may disappear soon. The TraceArguments class
  176. // provides a CopyStringTo() method to copy these strings into a
  177. // StringStorage instance, which is useful if the instance needs to
  178. // survive longer than the temporaries.
  179. //
  180. // - |as_convertable| is equivalent to
  181. // std::unique_ptr<ConvertableToTraceFormat>, except that it is a pointer
  182. // to keep this union POD and avoid un-necessary declarations and potential
  183. // code generation. This means that its ownership is passed to the
  184. // TraceValue instance when Init(std::unique_ptr<ConvertableToTraceFormat>)
  185. // is called, and that it will be deleted by the containing TraceArguments
  186. // destructor, or Reset() method.
  187. //
  188. union BASE_EXPORT TraceValue {
  189. bool as_bool;
  190. unsigned long long as_uint;
  191. long long as_int;
  192. double as_double;
  193. const void* as_pointer;
  194. const char* as_string;
  195. ConvertableToTraceFormat* as_convertable;
  196. // There is no constructor to keep this structure POD intentionally.
  197. // This avoids un-needed initialization when only 0 or 1 arguments are
  198. // used to construct a TraceArguments instance. Use Init() instead to
  199. // perform explicit initialization from a given C++ value.
  200. // Initialize TraceValue instance from a C++ trace value.
  201. // This relies on the proper specialization of TraceValue::Helper<>
  202. // described below. Usage is simply:
  203. //
  204. // TraceValue v;
  205. // v.Init(<value>);
  206. //
  207. // NOTE: For ConvertableToTraceFormat values, see the note above and
  208. // the one for TraceValue::Helper for CONVERTABLE_TYPE below.
  209. template <typename T>
  210. void Init(T&& value) {
  211. using ValueType = typename InnerType<T>::type;
  212. Helper<ValueType>::SetValue(this, std::forward<T>(value));
  213. }
  214. // Static method to create a new TraceValue instance from a given
  215. // initialization value. Note that this deduces the TRACE_VALUE_TYPE_XXX
  216. // type but doesn't return it, use ForType<T>::value for this.
  217. //
  218. // Usage example:
  219. // auto v = TraceValue::Make(100);
  220. // auto v2 = TraceValue::Make("Some text string");
  221. //
  222. // IMPORTANT: Experience shows that the compiler generates worse code when
  223. // using this method rather than calling Init() directly on an existing
  224. // TraceValue union :-(
  225. //
  226. template <typename T>
  227. static TraceValue Make(T&& value) {
  228. TraceValue ret;
  229. ret.Init(std::forward<T>(value));
  230. return ret;
  231. }
  232. // Output current value as a JSON string. |type| must be a valid
  233. // TRACE_VALUE_TYPE_XXX value.
  234. void AppendAsJSON(unsigned char type, std::string* out) const;
  235. // Output current value as a string. If the output string is to be used
  236. // in a JSON format use AppendAsJSON instead. |type| must be valid
  237. // TRACE_VALUE_TYPE_XXX value.
  238. void AppendAsString(unsigned char type, std::string* out) const;
  239. private:
  240. void Append(unsigned char type, bool as_json, std::string* out) const;
  241. // InnerType<T>::type removes reference, cv-qualifications and decays
  242. // function and arrays into pointers. Only used internally.
  243. template <typename T>
  244. struct InnerType {
  245. using type = typename std::remove_cv<typename std::remove_reference<
  246. typename std::decay<T>::type>::type>::type;
  247. };
  248. public:
  249. // TraceValue::Helper is used to provide information about initialization
  250. // value types and an initialization function. It is a struct that should
  251. // provide the following for supported initialization value types:
  252. //
  253. // - kType: is a static TRACE_VALUE_TYPE_XXX constant.
  254. //
  255. // - SetValue(TraceValue*, T): is a static inline method that sets
  256. // TraceValue value from a given T value. Second parameter type
  257. // can also be const T& or T&& to restrict uses.
  258. //
  259. // IMPORTANT: The type T must be InnerType<Q>, where Q is the real C++
  260. // argument type. I.e. you should not have to deal with reference types
  261. // in your specialization.
  262. //
  263. // Specializations are defined for integers, enums, floating point, pointers,
  264. // constant C string literals and pointers, std::string, time values below.
  265. //
  266. // Specializations for custom types are possible provided that there exists
  267. // a corresponding Helper specialization, for example:
  268. //
  269. // template <>
  270. // struct base::trace_event::TraceValue::Helper<Foo> {
  271. // static constexpr unsigned char kTypes = TRACE_VALUE_TYPE_COPY_STRING;
  272. // static inline void SetValue(TraceValue* v, const Foo& value) {
  273. // v->as_string = value.c_str();
  274. // }
  275. // };
  276. //
  277. // Will allow code like:
  278. //
  279. // Foo foo = ...;
  280. // auto v = TraceValue::Make(foo);
  281. //
  282. // Or even:
  283. // Foo foo = ...;
  284. // TraceArguments args("foo_arg1", foo);
  285. //
  286. template <typename T, class = void>
  287. struct Helper {};
  288. // TraceValue::TypeFor<T>::value returns the TRACE_VALUE_TYPE_XXX
  289. // corresponding to initialization values of type T.
  290. template <typename T>
  291. struct TypeFor {
  292. using ValueType = typename InnerType<T>::type;
  293. static const unsigned char value = Helper<ValueType>::kType;
  294. };
  295. // TraceValue::TypeCheck<T>::value is only defined iff T can be used to
  296. // initialize a TraceValue instance. This is useful to restrict template
  297. // instantiation to only the appropriate type (see TraceArguments
  298. // constructors below).
  299. template <typename T,
  300. class = decltype(TraceValue::Helper<
  301. typename TraceValue::InnerType<T>::type>::kType)>
  302. struct TypeCheck {
  303. static const bool value = true;
  304. };
  305. };
  306. // TraceValue::Helper for integers and enums.
  307. template <typename T>
  308. struct TraceValue::Helper<
  309. T,
  310. typename std::enable_if<std::is_integral<T>::value ||
  311. std::is_enum<T>::value>::type> {
  312. static constexpr unsigned char kType =
  313. std::is_signed<T>::value ? TRACE_VALUE_TYPE_INT : TRACE_VALUE_TYPE_UINT;
  314. static inline void SetValue(TraceValue* v, T value) {
  315. v->as_uint = static_cast<unsigned long long>(value);
  316. }
  317. };
  318. // TraceValue::Helper for floating-point types
  319. template <typename T>
  320. struct TraceValue::
  321. Helper<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
  322. static constexpr unsigned char kType = TRACE_VALUE_TYPE_DOUBLE;
  323. static inline void SetValue(TraceValue* v, T value) { v->as_double = value; }
  324. };
  325. // TraceValue::Helper for bool.
  326. template <>
  327. struct TraceValue::Helper<bool> {
  328. static constexpr unsigned char kType = TRACE_VALUE_TYPE_BOOL;
  329. static inline void SetValue(TraceValue* v, bool value) { v->as_bool = value; }
  330. };
  331. // TraceValue::Helper for generic pointer types.
  332. template <typename T>
  333. struct TraceValue::Helper<T*> {
  334. static constexpr unsigned char kType = TRACE_VALUE_TYPE_POINTER;
  335. static inline void SetValue(TraceValue* v,
  336. const typename std::decay<T>::type* value) {
  337. v->as_pointer = value;
  338. }
  339. };
  340. // TraceValue::Helper for raw persistent C strings.
  341. template <>
  342. struct TraceValue::Helper<const char*> {
  343. static constexpr unsigned char kType = TRACE_VALUE_TYPE_STRING;
  344. static inline void SetValue(TraceValue* v, const char* value) {
  345. v->as_string = value;
  346. }
  347. };
  348. // TraceValue::Helper for std::string values.
  349. template <>
  350. struct TraceValue::Helper<std::string> {
  351. static constexpr unsigned char kType = TRACE_VALUE_TYPE_COPY_STRING;
  352. static inline void SetValue(TraceValue* v, const std::string& value) {
  353. v->as_string = value.c_str();
  354. }
  355. };
  356. // Special case for scoped pointers to convertables to trace format.
  357. // |CONVERTABLE_TYPE| must be a type whose pointers can be converted to a
  358. // ConvertableToTraceFormat* pointer as well (e.g. a derived class).
  359. // IMPORTANT: This takes an std::unique_ptr<CONVERTABLE_TYPE> value, and takes
  360. // ownership of the pointed object!
  361. template <typename CONVERTABLE_TYPE>
  362. struct TraceValue::Helper<std::unique_ptr<CONVERTABLE_TYPE>,
  363. typename std::enable_if<std::is_convertible<
  364. CONVERTABLE_TYPE*,
  365. ConvertableToTraceFormat*>::value>::type> {
  366. static constexpr unsigned char kType = TRACE_VALUE_TYPE_CONVERTABLE;
  367. static inline void SetValue(TraceValue* v,
  368. std::unique_ptr<CONVERTABLE_TYPE> value) {
  369. v->as_convertable = value.release();
  370. }
  371. };
  372. // Specialization for time-based values like base::Time, which provide a
  373. // a ToInternalValue() method.
  374. template <typename T>
  375. struct TraceValue::Helper<
  376. T,
  377. typename std::enable_if<std::is_same<T, base::Time>::value ||
  378. std::is_same<T, base::TimeTicks>::value ||
  379. std::is_same<T, base::ThreadTicks>::value>::type> {
  380. static constexpr unsigned char kType = TRACE_VALUE_TYPE_INT;
  381. static inline void SetValue(TraceValue* v, const T& value) {
  382. v->as_int = value.ToInternalValue();
  383. }
  384. };
  385. // Simple container for const char* that should be copied instead of retained.
  386. // The goal is to indicate that the C string is copyable, unlike the default
  387. // Init(const char*) implementation. Usage is:
  388. //
  389. // const char* str = ...;
  390. // v.Init(TraceStringWithCopy(str));
  391. //
  392. // Which will mark the string as TRACE_VALUE_TYPE_COPY_STRING, instead of
  393. // TRACE_VALUE_TYPE_STRING.
  394. //
  395. class TraceStringWithCopy {
  396. public:
  397. explicit TraceStringWithCopy(const char* str) : str_(str) {}
  398. const char* str() const { return str_; }
  399. private:
  400. const char* str_;
  401. };
  402. template <>
  403. struct TraceValue::Helper<TraceStringWithCopy> {
  404. static constexpr unsigned char kType = TRACE_VALUE_TYPE_COPY_STRING;
  405. static inline void SetValue(TraceValue* v, const TraceStringWithCopy& value) {
  406. v->as_string = value.str();
  407. }
  408. };
  409. class TraceArguments;
  410. // A small class used to store a copy of all strings from a given
  411. // TraceArguments instance (see below). When empty, this should only
  412. // take the size of a pointer. Otherwise, this will point to a heap
  413. // allocated block containing a size_t value followed by all characters
  414. // in the storage area. For most cases, this is more efficient
  415. // than using a std::unique_ptr<std::string> or an std::vector<char>.
  416. class BASE_EXPORT StringStorage {
  417. public:
  418. constexpr StringStorage() = default;
  419. explicit StringStorage(size_t alloc_size) { Reset(alloc_size); }
  420. ~StringStorage() {
  421. if (data_)
  422. ::free(data_);
  423. }
  424. StringStorage(StringStorage&& other) noexcept : data_(other.data_) {
  425. other.data_ = nullptr;
  426. }
  427. StringStorage& operator=(StringStorage&& other) noexcept {
  428. if (this != &other) {
  429. if (data_)
  430. ::free(data_);
  431. data_ = other.data_;
  432. other.data_ = nullptr;
  433. }
  434. return *this;
  435. }
  436. // Reset storage area to new allocation size. Existing content might not
  437. // be preserved. If |alloc_size| is 0, this will free the storage area
  438. // as well.
  439. void Reset(size_t alloc_size = 0);
  440. // Accessors.
  441. constexpr size_t size() const { return data_ ? data_->size : 0u; }
  442. constexpr const char* data() const { return data_ ? data_->chars : nullptr; }
  443. constexpr char* data() { return data_ ? data_->chars : nullptr; }
  444. constexpr const char* begin() const { return data(); }
  445. constexpr const char* end() const { return data() + size(); }
  446. inline char* begin() { return data(); }
  447. inline char* end() { return data() + size(); }
  448. // True iff storage is empty.
  449. constexpr bool empty() const { return size() == 0; }
  450. // Returns true if |ptr| is inside the storage area, false otherwise.
  451. // Used during unit-testing.
  452. constexpr bool Contains(const void* ptr) const {
  453. const char* char_ptr = static_cast<const char*>(ptr);
  454. return (char_ptr >= begin() && char_ptr < end());
  455. }
  456. // Returns true if all string pointers in |args| are contained in this
  457. // storage area.
  458. bool Contains(const TraceArguments& args) const;
  459. // Return an estimate of the memory overhead of this instance. This doesn't
  460. // count the size of |data_| itself.
  461. constexpr size_t EstimateTraceMemoryOverhead() const {
  462. return data_ ? sizeof(size_t) + data_->size : 0u;
  463. }
  464. private:
  465. // Heap allocated data block (variable size), made of:
  466. //
  467. // - size: a size_t field, giving the size of the following |chars| array.
  468. // - chars: an array of |size| characters, holding all zero-terminated
  469. // strings referenced from a TraceArguments instance.
  470. struct Data {
  471. size_t size = 0;
  472. char chars[1]; // really |size| character items in storage.
  473. };
  474. // This is an owning pointer. Normally, using a std::unique_ptr<> would be
  475. // enough, but the compiler will then complaing about inlined constructors
  476. // and destructors being too complex (!), resulting in larger code for no
  477. // good reason.
  478. Data* data_ = nullptr;
  479. };
  480. // TraceArguments models an array of kMaxSize trace-related items,
  481. // each one of them having:
  482. // - a name, which is a constant char array literal.
  483. // - a type, as described by TRACE_VALUE_TYPE_XXX macros.
  484. // - a value, stored in a TraceValue union.
  485. //
  486. // IMPORTANT: For TRACE_VALUE_TYPE_CONVERTABLE, the value holds an owning
  487. // pointer to an AsConvertableToTraceFormat instance, which will
  488. // be destroyed with the array (or moved out of it when passed
  489. // to a TraceEvent instance).
  490. //
  491. // For TRACE_VALUE_TYPE_COPY_STRING, the value holds a const char* pointer
  492. // whose content will be copied when creating a TraceEvent instance.
  493. //
  494. // IMPORTANT: Most constructors and the destructor are all inlined
  495. // intentionally, in order to let the compiler remove un-necessary operations
  496. // and reduce machine code.
  497. //
  498. class BASE_EXPORT TraceArguments {
  499. public:
  500. // Maximum number of arguments held by this structure.
  501. static constexpr size_t kMaxSize = 2;
  502. // Default constructor, no arguments.
  503. TraceArguments() : size_(0) {}
  504. // Constructor for a single argument.
  505. template <typename T, class = decltype(TraceValue::TypeCheck<T>::value)>
  506. TraceArguments(const char* arg1_name, T&& arg1_value) : size_(1) {
  507. types_[0] = TraceValue::TypeFor<T>::value;
  508. names_[0] = arg1_name;
  509. values_[0].Init(std::forward<T>(arg1_value));
  510. }
  511. // Constructor for two arguments.
  512. template <typename T1,
  513. typename T2,
  514. class = decltype(TraceValue::TypeCheck<T1>::value &&
  515. TraceValue::TypeCheck<T2>::value)>
  516. TraceArguments(const char* arg1_name,
  517. T1&& arg1_value,
  518. const char* arg2_name,
  519. T2&& arg2_value)
  520. : size_(2) {
  521. types_[0] = TraceValue::TypeFor<T1>::value;
  522. types_[1] = TraceValue::TypeFor<T2>::value;
  523. names_[0] = arg1_name;
  524. names_[1] = arg2_name;
  525. values_[0].Init(std::forward<T1>(arg1_value));
  526. values_[1].Init(std::forward<T2>(arg2_value));
  527. }
  528. // Constructor used to convert a legacy set of arguments when there
  529. // are no convertable values at all.
  530. TraceArguments(int num_args,
  531. const char* const* arg_names,
  532. const unsigned char* arg_types,
  533. const unsigned long long* arg_values);
  534. // Constructor used to convert legacy set of arguments, where the
  535. // convertable values are also provided by an array of CONVERTABLE_TYPE.
  536. template <typename CONVERTABLE_TYPE>
  537. TraceArguments(int num_args,
  538. const char* const* arg_names,
  539. const unsigned char* arg_types,
  540. const unsigned long long* arg_values,
  541. CONVERTABLE_TYPE* arg_convertables) {
  542. static int max_args = static_cast<int>(kMaxSize);
  543. if (num_args > max_args)
  544. num_args = max_args;
  545. size_ = static_cast<unsigned char>(num_args);
  546. for (size_t n = 0; n < size_; ++n) {
  547. types_[n] = arg_types[n];
  548. names_[n] = arg_names[n];
  549. if (arg_types[n] == TRACE_VALUE_TYPE_CONVERTABLE) {
  550. values_[n].Init(
  551. std::forward<CONVERTABLE_TYPE>(std::move(arg_convertables[n])));
  552. } else {
  553. values_[n].as_uint = arg_values[n];
  554. }
  555. }
  556. }
  557. // Destructor. NOTE: Intentionally inlined (see note above).
  558. ~TraceArguments() {
  559. for (size_t n = 0; n < size_; ++n) {
  560. if (types_[n] == TRACE_VALUE_TYPE_CONVERTABLE)
  561. delete values_[n].as_convertable;
  562. }
  563. }
  564. // Disallow copy operations.
  565. TraceArguments(const TraceArguments&) = delete;
  566. TraceArguments& operator=(const TraceArguments&) = delete;
  567. // Allow move operations.
  568. TraceArguments(TraceArguments&& other) noexcept {
  569. ::memcpy(this, &other, sizeof(*this));
  570. // All owning pointers were copied to |this|. Setting |other.size_| will
  571. // mask the pointer values still in |other|.
  572. other.size_ = 0;
  573. }
  574. TraceArguments& operator=(TraceArguments&&) noexcept;
  575. // Accessors
  576. size_t size() const { return size_; }
  577. const unsigned char* types() const { return types_; }
  578. const char* const* names() const { return names_; }
  579. const TraceValue* values() const { return values_; }
  580. // Reset to empty arguments list.
  581. void Reset();
  582. // Use |storage| to copy all copyable strings.
  583. // If |copy_all_strings| is false, then only the TRACE_VALUE_TYPE_COPY_STRING
  584. // values will be copied into storage. If it is true, then argument names are
  585. // also copied to storage, as well as the strings pointed to by
  586. // |*extra_string1| and |*extra_string2|.
  587. // NOTE: If there are no strings to copy, |*storage| is left untouched.
  588. void CopyStringsTo(StringStorage* storage,
  589. bool copy_all_strings,
  590. const char** extra_string1,
  591. const char** extra_string2);
  592. // Append debug string representation to |*out|.
  593. void AppendDebugString(std::string* out);
  594. private:
  595. unsigned char size_;
  596. unsigned char types_[kMaxSize];
  597. const char* names_[kMaxSize];
  598. TraceValue values_[kMaxSize];
  599. };
  600. } // namespace trace_event
  601. } // namespace base
  602. #endif // BASE_TRACE_EVENT_TRACE_ARGUMENTS_H_