| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef LIB_INSPECT_CPP_VMO_TYPES_H_ |
| #define LIB_INSPECT_CPP_VMO_TYPES_H_ |
| |
| #include <lib/fit/function.h> |
| #include <lib/fit/thread_safety.h> |
| #include <lib/fpromise/promise.h> |
| #include <lib/inspect/cpp/vmo/block.h> |
| #include <lib/stdcompat/optional.h> |
| #include <lib/stdcompat/span.h> |
| #include <lib/stdcompat/string_view.h> |
| #include <lib/stdcompat/variant.h> |
| #include <zircon/assert.h> |
| #include <zircon/compiler.h> |
| #include <zircon/types.h> |
| |
| #include <cstddef> |
| #include <cstdint> |
| #include <functional> |
| #include <mutex> |
| #include <string> |
| #include <type_traits> |
| #include <vector> |
| |
| namespace inspect { |
| class Node; |
| class Inspector; |
| |
| using LazyNodeCallbackFn = fit::function<fpromise::promise<Inspector>()>; |
| using AtomicUpdateCallbackFn = fit::function<void(Node&)>; |
| using RecordChildCallbackFn = fit::function<void(Node&)>; |
| |
| // StringReference is a type that can be used as a name of a Node in the Inspect API. |
| // Each StringReference will have a single allocation in the appropriate VMO. |
| // StringReferences are lazy-node safe. |
| // |
| // StringReferences can be statically declared as a constant in namespace-scope. |
| // Example: |
| // |
| // `namespace {` |
| // `const StringReference kTimestamp("timestamp");` |
| // `} // namespace` |
| // |
| // Or, |
| // `static const StringReference kTimestamp("timestamp");` |
| class StringReference final { |
| public: |
| StringReference(StringReference&&) = default; |
| StringReference(const StringReference&) = default; |
| |
| // Create a new `StringReference` for the given value. |
| // |
| // StringReference treats the data as borrowed; the caller is responsible for lifetime |
| // management. `data` must live as long as the StringReference. `data` must be null |
| // terminated. |
| explicit StringReference(const char* data); |
| |
| // Access the data referenced by `this`. |
| cpp17::string_view Data() const; |
| |
| // Access the state ID of the StringReference. |
| uint64_t ID() const; |
| |
| private: |
| StringReference() = delete; |
| const cpp17::string_view data_; |
| const uint64_t reference_id_; |
| }; |
| |
| // `BorrowedStringValue` is a non-owning polymorphic type that allows the discrimination between |
| // single-use StringReference-as-names and user-declared StringReferences that have |
| // a re-usable state ID. This allows us to not do the work associated with maintaining |
| // the state ID when unnecessary. |
| using BorrowedStringValue = cpp17::variant<cpp17::string_view, StringReference>; |
| |
| namespace internal { |
| class State; |
| |
| // Base class for ValueHolder types, which approximate std::any. |
| struct BaseHolder { |
| virtual ~BaseHolder() = default; |
| }; |
| |
| // Holder for an arbitrary type. |
| template <typename T> |
| struct ValueHolder final : public BaseHolder { |
| explicit ValueHolder(T val) : value(std::move(val)) {} |
| ~ValueHolder() override = default; |
| T value; |
| }; |
| |
| // A property containing a templated numeric type. All methods wrap the |
| // corresponding functionality on |State|, and concrete |
| // implementations are available only for int64_t, uint64_t and double. |
| template <typename T> |
| class NumericProperty final { |
| public: |
| // Construct a default numeric metric. Operations on this metric are |
| // no-ops. |
| NumericProperty() = default; |
| ~NumericProperty(); |
| |
| // Allow moving, disallow copying. |
| NumericProperty(const NumericProperty& other) = delete; |
| NumericProperty(NumericProperty&& other) = default; |
| NumericProperty& operator=(const NumericProperty& other) = delete; |
| NumericProperty& operator=(NumericProperty&& other) noexcept; |
| |
| // Set the value of this numeric metric to the given value. |
| void Set(T value); |
| |
| // Add the given value to the value of this numeric metric. |
| void Add(T value); |
| |
| // Subtract the given value from the value of this numeric metric. |
| void Subtract(T value); |
| |
| // Return true if this metric is stored in a buffer. False otherwise. |
| explicit operator bool() const { return state_ != nullptr; } |
| |
| private: |
| friend class ::inspect::internal::State; |
| NumericProperty(std::shared_ptr<internal::State> state, internal::BlockIndex name, |
| internal::BlockIndex value) |
| : state_(std::move(state)), name_index_(name), value_index_(value) {} |
| |
| // Reference to the state containing this metric. |
| std::shared_ptr<internal::State> state_; |
| |
| // Index of the name block in the state. |
| internal::BlockIndex name_index_; |
| |
| // Index of the value block in the state. |
| internal::BlockIndex value_index_; |
| }; |
| |
| // A value containing an array of numeric types. All methods wrap the |
| // corresponding functionality on |State|, and concrete |
| // implementations are available only for int64_t, uint64_t and double. |
| template <typename T> |
| class ArrayValue final { |
| public: |
| // Construct a default array value. Operations on this value are |
| // no-ops. |
| ArrayValue() = default; |
| ~ArrayValue(); |
| |
| // Allow moving, disallow copying. |
| ArrayValue(const ArrayValue& other) = delete; |
| ArrayValue(ArrayValue&& other) = default; |
| ArrayValue& operator=(const ArrayValue& other) = delete; |
| ArrayValue& operator=(ArrayValue&& other) noexcept; |
| |
| // Set the value of the given index of this array. |
| void Set(size_t index, T value); |
| |
| // Add the given value to the value of this numeric metric. |
| template <typename X = T, |
| typename = std::enable_if_t<!std::is_same<X, BorrowedStringValue>::value>> |
| void Add(size_t index, T value); |
| |
| // Subtract the given value from the value of this numeric metric. |
| template <typename X = T, |
| typename = std::enable_if_t<!std::is_same<X, BorrowedStringValue>::value>> |
| void Subtract(size_t index, T value); |
| |
| // Return true if this metric is stored in a buffer. False otherwise. |
| explicit operator bool() const { return state_ != nullptr; } |
| |
| private: |
| friend class ::inspect::internal::State; |
| ArrayValue(std::shared_ptr<internal::State> state, internal::BlockIndex name, |
| internal::BlockIndex value) |
| : state_(std::move(state)), name_index_(name), value_index_(value) {} |
| |
| // Reference to the state containing this value. |
| std::shared_ptr<internal::State> state_; |
| |
| // Index of the name block in the state. |
| internal::BlockIndex name_index_; |
| |
| // Index of the value block in the state. |
| internal::BlockIndex value_index_; |
| }; |
| |
| template <typename T> |
| class LinearHistogram final { |
| public: |
| // Create a default histogram. |
| // Operations on the metric will have no effect. |
| LinearHistogram() = default; |
| |
| // Movable but not copyable. |
| LinearHistogram(const LinearHistogram& other) = delete; |
| LinearHistogram(LinearHistogram&& other) = default; |
| LinearHistogram& operator=(const LinearHistogram& other) = delete; |
| LinearHistogram& operator=(LinearHistogram&& other) = default; |
| |
| // Insert the given value once to the correct bucket of the histogram. |
| void Insert(T value) { Insert(value, 1); } |
| |
| // Insert the given value |count| times to the correct bucket of the |
| // histogram. |
| void Insert(T value, T count) { array_.Add(GetIndexForValue(value), count); } |
| |
| private: |
| friend class ::inspect::Node; |
| |
| // First slots are floor, step_size, and underflow. |
| static const size_t kBucketOffset = 3; |
| |
| // Get the number of buckets, which excludes the two parameter slots and the |
| // two overflow slots. |
| size_t BucketCount() { return array_size_ - 4; } |
| |
| // Calculates the correct array index to store the given value. |
| size_t GetIndexForValue(T value) { |
| if (array_size_ == 0) { |
| return 0; |
| } |
| size_t ret = kBucketOffset - 1; |
| T current_floor = floor_; |
| for (; value >= current_floor && ret < array_size_ - 1; current_floor += step_size_, ret++) { |
| } |
| return ret; |
| } |
| |
| // Internal constructor wrapping an array. |
| LinearHistogram(T floor, T step_size, size_t array_size, ArrayValue<T> array) |
| : floor_(floor), step_size_(step_size), array_size_(array_size), array_(std::move(array)) { |
| ZX_ASSERT(array_size_ > 4); |
| array_.Set(0, floor_); |
| array_.Set(1, step_size_); |
| } |
| |
| T floor_ = 0; |
| T step_size_ = 0; |
| size_t array_size_ = 0; |
| ArrayValue<T> array_; |
| }; |
| |
| template <typename T> |
| class ExponentialHistogram final { |
| public: |
| // Create a default histogram. |
| // Operations on the metric will have no effect. |
| ExponentialHistogram() = default; |
| |
| // Movable but not copyable. |
| ExponentialHistogram(const ExponentialHistogram& other) = delete; |
| ExponentialHistogram(ExponentialHistogram&& other) = default; |
| ExponentialHistogram& operator=(const ExponentialHistogram& other) = delete; |
| ExponentialHistogram& operator=(ExponentialHistogram&& other) = default; |
| |
| // Insert the given value once to the correct bucket of the histogram. |
| void Insert(T value) { Insert(value, 1); } |
| |
| // Insert the given value |count| times to the correct bucket of the |
| // histogram. |
| void Insert(T value, T count) { array_.Add(GetIndexForValue(value), count); } |
| |
| private: |
| friend class ::inspect::Node; |
| |
| // First slots are floor, initial_step, step_multiplier, and underflow. |
| static const size_t kBucketOffset = 4; |
| |
| // Get the number of buckets, which excludes the two parameter slots and the |
| // two overflow slots. |
| size_t BucketCount() { return array_size_ - 5; } |
| |
| // Calculates the correct array index to store the given value. |
| size_t GetIndexForValue(T value) { |
| if (array_size_ == 0) { |
| return 0; |
| } |
| T current_floor = floor_; |
| T current_step = initial_step_; |
| size_t ret = kBucketOffset - 1; |
| while (value >= current_floor && ret < array_size_ - 1) { |
| current_floor = floor_ + current_step; |
| current_step *= step_multiplier_; |
| ret++; |
| } |
| return ret; |
| } |
| |
| // Internal constructor wrapping a VMO type. |
| ExponentialHistogram(T floor, T initial_step, T step_multiplier, size_t array_size, |
| ArrayValue<T> array) |
| : floor_(floor), |
| initial_step_(initial_step), |
| step_multiplier_(step_multiplier), |
| array_size_(array_size), |
| array_(std::move(array)) { |
| ZX_ASSERT(array_size_ > 5); |
| array_.Set(0, floor_); |
| array_.Set(1, initial_step_); |
| array_.Set(2, step_multiplier_); |
| } |
| |
| T floor_ = 0; |
| T initial_step_ = 0; |
| T step_multiplier_ = 0; |
| size_t array_size_ = 0; |
| ArrayValue<T> array_; |
| }; |
| |
| // A property containing a string value. |
| // All methods wrap the corresponding functionality on |State|. |
| template <typename T> |
| class Property final { |
| public: |
| // Construct a default property. Operations on this property are |
| // no-ops. |
| Property() = default; |
| ~Property(); |
| |
| // Allow moving, disallow copying. |
| Property(const Property& other) = delete; |
| Property(Property&& other) = default; |
| Property& operator=(const Property& other) = delete; |
| Property& operator=(Property&& other) noexcept; |
| |
| // Return true if this property is stored in a buffer. False otherwise. |
| explicit operator bool() const { return state_ != nullptr; } |
| |
| // Set the value of this property. |
| void Set(const T& value); |
| |
| private: |
| friend class ::inspect::internal::State; |
| Property(std::shared_ptr<internal::State> state, internal::BlockIndex name, |
| internal::BlockIndex value) |
| : state_(std::move(state)), name_index_(name), value_index_(value) {} |
| |
| // Reference to the state containing this property. |
| std::shared_ptr<internal::State> state_; |
| |
| // Index of the name block in the state. |
| internal::BlockIndex name_index_; |
| |
| // Index of the value block in the state. |
| internal::BlockIndex value_index_; |
| }; |
| |
| } // namespace internal |
| |
| using IntProperty = internal::NumericProperty<int64_t>; |
| using UintProperty = internal::NumericProperty<uint64_t>; |
| using DoubleProperty = internal::NumericProperty<double>; |
| using BoolProperty = internal::Property<bool>; |
| |
| using IntArray = internal::ArrayValue<int64_t>; |
| using UintArray = internal::ArrayValue<uint64_t>; |
| using DoubleArray = internal::ArrayValue<double>; |
| using StringArray = internal::ArrayValue<BorrowedStringValue>; |
| |
| using LinearIntHistogram = internal::LinearHistogram<int64_t>; |
| using LinearUintHistogram = internal::LinearHistogram<uint64_t>; |
| using LinearDoubleHistogram = internal::LinearHistogram<double>; |
| |
| using ExponentialIntHistogram = internal::ExponentialHistogram<int64_t>; |
| using ExponentialUintHistogram = internal::ExponentialHistogram<uint64_t>; |
| using ExponentialDoubleHistogram = internal::ExponentialHistogram<double>; |
| |
| using StringProperty = internal::Property<std::string>; |
| using ByteVectorProperty = internal::Property<std::vector<uint8_t>>; |
| |
| // Links specify a location that can be read as a continuation of an Inspect hierarchy. |
| class Link final { |
| public: |
| // Construct a default link. |
| Link() = default; |
| ~Link(); |
| |
| // Allow moving, disallow copying. |
| Link(const Link& other) = delete; |
| Link(Link&& other) = default; |
| Link& operator=(const Link& other) = delete; |
| Link& operator=(Link&& other) noexcept; |
| |
| // Return true if this node is stored in a buffer. False otherwise. |
| explicit operator bool() const { return state_ != nullptr; } |
| |
| private: |
| friend class ::inspect::internal::State; |
| Link(std::shared_ptr<internal::State> state, internal::BlockIndex name, |
| internal::BlockIndex value, internal::BlockIndex content) |
| : state_(std::move(state)), name_index_(name), value_index_(value), content_index_(content) {} |
| |
| // Remove from `state_` and invalidate `state_`. |
| // This needs to be done on destruction and move. |
| void DeallocateFromVmo(); |
| |
| // Reference to the state containing this value. |
| std::shared_ptr<internal::State> state_; |
| |
| // Index of the name block in the state. |
| internal::BlockIndex name_index_; |
| |
| // Index of the value block in the state. |
| internal::BlockIndex value_index_; |
| |
| // Index of the content block in the state. |
| internal::BlockIndex content_index_; |
| }; |
| |
| // A LazyNode has a value that is dynamically set by a callback. |
| class LazyNode final { |
| public: |
| // Construct a default LazyNode. |
| LazyNode() = default; |
| ~LazyNode(); |
| |
| // Allow moving, disallow copying. |
| LazyNode(const LazyNode& other) = delete; |
| LazyNode(LazyNode&& other) = default; |
| LazyNode& operator=(const LazyNode& other) = delete; |
| LazyNode& operator=(LazyNode&& other) noexcept; |
| |
| // Return true if this value is represented in a buffer. False otherwise. |
| explicit operator bool() const { return state_ != nullptr; } |
| |
| private: |
| friend class ::inspect::internal::State; |
| LazyNode(std::shared_ptr<internal::State> state, std::string content_value, Link link) |
| : state_(std::move(state)), |
| content_value_(std::move(content_value)), |
| link_(std::move(link)) {} |
| |
| // Remove from `state_` and invalidate `state_`. |
| // This needs to be done on destruction and move. |
| void DeallocateFromVmo(); |
| |
| // Reference to the state containing this value. |
| std::shared_ptr<internal::State> state_; |
| |
| // The value stored in the contents of the Link for this node. Used as a key for removal when |
| // deleted. |
| std::string content_value_; |
| |
| // The Link node that references this LazyNode. |
| Link link_; |
| }; |
| |
| namespace internal { |
| enum StringReferenceWrapperDiscriminant { |
| isStringLiteral, |
| isStringReference, |
| }; |
| |
| class InnerValueList final { |
| public: |
| InnerValueList() = default; |
| |
| // Disallow copy and assign. |
| InnerValueList(const InnerValueList&) = delete; |
| InnerValueList(InnerValueList&& other) = delete; |
| InnerValueList& operator=(const InnerValueList&) = delete; |
| InnerValueList& operator=(InnerValueList&& other) = delete; |
| |
| // Emplaces a value in this ValueList. |
| template <typename T> |
| void emplace(T value) { |
| std::lock_guard<std::mutex> lock(mutex_); |
| values_.emplace_back(std::make_unique<internal::ValueHolder<T>>(std::move(value))); |
| } |
| |
| void clear() { |
| std::lock_guard<std::mutex> lock(mutex_); |
| values_.clear(); |
| } |
| |
| private: |
| mutable std::mutex mutex_; |
| // The list of values. |
| std::vector<std::unique_ptr<internal::BaseHolder>> values_ FIT_GUARDED(mutex_); |
| }; |
| |
| } // namespace internal |
| |
| // A ValueList is a holder for arbitrary values that do not need to be explicitly named or modified |
| // after creation. |
| // |
| // This class is not thread-safe, and it requires external synchronization if accessed from multiple |
| // threads. |
| // |
| // Example: |
| // struct Item { |
| // // The inspect::Node for this item. |
| // Node node; |
| // |
| // // List of unnamed values that should be retained for this item. |
| // ValueList values; |
| // |
| // Item(Node* parent, const std::string& name, int value) { |
| // node = parent->CreateChild(name); |
| // // Expose the value, but enlist it in the ValueList so it doesn't need a name. |
| // node.CreateInt("value", value, &values); |
| // // "Stats" computes and stores some stats under the node it is given. Keep this in the |
| // // ValueList as well since it doesn't need a name. |
| // values.emplace(Stats(this, node.CreateChild("stats"))); |
| // } |
| // } |
| class ValueList final { |
| public: |
| ValueList() { list_ = std::make_shared<internal::InnerValueList>(); } |
| |
| // Disallow copy and assign. |
| // ValueList(const ValueList&) = delete; |
| // ValueList(ValueList&& other) = delete; |
| // ValueList& operator=(const ValueList&) = delete; |
| // ValueList& operator=(ValueList&& other) = delete; |
| |
| // Emplaces a value in this ValueList. |
| template <typename T> |
| void emplace(T value) { |
| list_->emplace(std::move(value)); |
| } |
| |
| void clear() { list_->clear(); } |
| |
| private: |
| std::shared_ptr<internal::InnerValueList> list_; |
| }; |
| |
| // A node under which properties, metrics, and other nodes may be nested. |
| // All methods wrap the corresponding functionality on |State|. |
| class Node final { |
| public: |
| // Construct a default node. Operations on this node are |
| // no-ops. |
| Node() = default; |
| ~Node(); |
| |
| // Allow moving, disallow copying. |
| Node(const Node& other) = delete; |
| Node(Node&& other) = default; |
| Node& operator=(const Node& other) = delete; |
| Node& operator=(Node&& other) noexcept; |
| |
| // Create a new |Node| with the given name that is a child of this node. |
| // If this node is not stored in a buffer, the created node will |
| // also not be stored in a buffer. |
| Node CreateChild(BorrowedStringValue name) __WARN_UNUSED_RESULT; |
| |
| // Same as CreateChild, but emplaces the value in the given container. |
| // |
| // The type of |list| must have method emplace(Node). |
| // inspect::ValueList is recommended for most use cases. |
| template <typename T> |
| void CreateChild(BorrowedStringValue name, T* list) { |
| list->emplace(CreateChild(name)); |
| } |
| |
| /// Associates the lifetime of the given value with the node lifetime. |
| template <typename T> |
| void Record(T value) { |
| value_list_.emplace(std::move(value)); |
| } |
| |
| // Create a new |Node| with the given name that is a child of this node. |
| // The new child lifetime will be the same as the parent node. |
| void RecordChild(BorrowedStringValue name, RecordChildCallbackFn callback); |
| |
| // Create a new |IntProperty| with the given name that is a child of this node. |
| // If this node is not stored in a buffer, the created metric will |
| // also not be stored in a buffer. |
| IntProperty CreateInt(BorrowedStringValue name, int64_t value) __WARN_UNUSED_RESULT; |
| |
| // Create a new |IntProperty| with the given name that is a child of this node. |
| // The new property lifetime will be the same as the parent node. |
| void RecordInt(BorrowedStringValue name, int64_t value); |
| |
| // Same as CreateInt, but emplaces the value in the given container. |
| // |
| // The type of |list| must have method emplace(IntProperty). |
| // inspect::ValueList is recommended for most use cases. |
| template <typename T> |
| void CreateInt(BorrowedStringValue name, int64_t value, T* list) { |
| list->emplace(CreateInt(name, value)); |
| } |
| |
| // Create a new |UintProperty| with the given name that is a child of this node. |
| // If this node is not stored in a buffer, the created metric will |
| // also not be stored in a buffer. |
| UintProperty CreateUint(BorrowedStringValue name, uint64_t value) __WARN_UNUSED_RESULT; |
| |
| // Create a new |UintProperty| with the given name that is a child of this node. |
| // The new property lifetime will be the same as the parent node. |
| void RecordUint(BorrowedStringValue name, uint64_t value); |
| |
| // Same as CreateUint, but emplaces the value in the given container. |
| // |
| // The type of |list| must have method emplace(UintProperty). |
| // inspect::ValueList is recommended for most use cases. |
| template <typename T> |
| void CreateUint(BorrowedStringValue name, uint64_t value, T* list) { |
| list->emplace(CreateUint(name, value)); |
| } |
| |
| // Create a new |DoubleProperty| with the given name that is a child of this node. |
| // If this node is not stored in a buffer, the created metric will |
| // also not be stored in a buffer. |
| DoubleProperty CreateDouble(BorrowedStringValue name, double value) __WARN_UNUSED_RESULT; |
| |
| // Create a new |DoubleProperty| with the given name that is a child of this node. |
| // The new property lifetime will be the same as the parent node. |
| void RecordDouble(BorrowedStringValue name, double value); |
| |
| // Same as CreateDouble, but emplaces the value in the given container. |
| // |
| // The type of |list| must have method emplace(DoubleProperty). |
| // inspect::ValueList is recommended for most use cases. |
| template <typename T> |
| void CreateDouble(BorrowedStringValue name, double value, T* list) { |
| list->emplace(CreateDouble(name, value)); |
| } |
| |
| // Create a new |BoolProperty| with the given name that is a child of this node. |
| // If this node is not stored in a buffer, the created metric will |
| // also not be stored in a buffer. |
| BoolProperty CreateBool(BorrowedStringValue name, bool value) __WARN_UNUSED_RESULT; |
| |
| // Create a new |BoolProperty| with the given name that is a child of this node. |
| // The new property lifetime will be the same as the parent node. |
| void RecordBool(BorrowedStringValue name, bool value); |
| |
| // Same as CreateBool, but emplaces the value in the given container. |
| // |
| // The type of |list| must have method emplace(BoolProperty). |
| // inspect::ValueList is recommended for most use cases. |
| template <typename T> |
| void CreateBool(BorrowedStringValue name, bool value, T* list) { |
| list->emplace(CreateBool(name, value)); |
| } |
| |
| // Create a new |StringProperty| with the given name and value that is a child of this node. |
| // If this node is not stored in a buffer, the created property will |
| // also not be stored in a buffer. |
| StringProperty CreateString(BorrowedStringValue name, |
| const std::string& value) __WARN_UNUSED_RESULT; |
| |
| // Create a new |StringProperty| with the given name that is a child of this node. |
| // The new property lifetime will be the same as the parent node. |
| void RecordString(BorrowedStringValue name, const std::string& value); |
| |
| // Same as CreateString, but emplaces the value in the given container. |
| // |
| // The type of |list| must have method emplace(StringProperty). |
| // inspect::ValueList is recommended for most use cases. |
| template <typename T> |
| void CreateString(BorrowedStringValue name, const std::string& value, T* list) { |
| list->emplace(CreateString(name, value)); |
| } |
| |
| // Create a new |ByteVectorProperty| with the given name and value that is a child of this node. |
| // If this node is not stored in a buffer, the created property will |
| // also not be stored in a buffer. |
| ByteVectorProperty CreateByteVector(BorrowedStringValue name, |
| cpp20::span<const uint8_t> value) __WARN_UNUSED_RESULT; |
| |
| // Create a new |ByteVectorProperty| with the given name that is a child of this node. |
| // The new property lifetime will be the same as the parent node. |
| void RecordByteVector(BorrowedStringValue name, cpp20::span<const uint8_t> value); |
| |
| // Same as CreateByteVector, but emplaces the value in the given container. |
| // |
| // The type of |list| must have method emplace(ByteVectorProperty). |
| // inspect::ValueList is recommended for most use cases. |
| template <typename T> |
| void CreateByteVector(BorrowedStringValue name, cpp20::span<const uint8_t> value, T* list) { |
| list->emplace(CreateByteVector(name, value)); |
| } |
| |
| // Create a new |IntArray| with the given name and slots that is a child of this node. |
| // If this node is not stored in a buffer, the created value will |
| // also not be stored in a buffer. |
| IntArray CreateIntArray(BorrowedStringValue name, size_t slots) __WARN_UNUSED_RESULT; |
| |
| // Create a new |UintArray| with the given name and slots that is a child of this node. |
| // If this node is not stored in a buffer, the created value will |
| // also not be stored in a buffer. |
| UintArray CreateUintArray(BorrowedStringValue name, size_t slots) __WARN_UNUSED_RESULT; |
| |
| // Create a new |DoubleArray| with the given name and slots that is a child of this node. |
| // If this node is not stored in a buffer, the created value will |
| // also not be stored in a buffer. |
| DoubleArray CreateDoubleArray(BorrowedStringValue name, size_t slots) __WARN_UNUSED_RESULT; |
| |
| // Create a new |StringArray| with the given name and slots that is a child of this node. |
| // If this node is not stored in a buffer, the created value will |
| // also not be stored in a buffer. |
| StringArray CreateStringArray(BorrowedStringValue name, size_t slots) __WARN_UNUSED_RESULT; |
| |
| // Create a new |LinearIntHistogram| with the given name and format that is a child of this |
| // node. If this node is not stored in a buffer, the created value will also not be stored in |
| // a buffer. |
| LinearIntHistogram CreateLinearIntHistogram(BorrowedStringValue name, int64_t floor, |
| int64_t step_size, |
| size_t buckets) __WARN_UNUSED_RESULT; |
| |
| // Create a new |LinearUintHistogram| with the given name and format that is a child of this |
| // node. If this node is not stored in a buffer, the created value will also not be stored in |
| // a buffer. |
| LinearUintHistogram CreateLinearUintHistogram(BorrowedStringValue name, uint64_t floor, |
| uint64_t step_size, |
| size_t buckets) __WARN_UNUSED_RESULT; |
| |
| // Create a new |LinearDoubleHistogram| with the given name and format that is a child of this |
| // node. If this node is not stored in a buffer, the created value will also not be stored in |
| // a buffer. |
| LinearDoubleHistogram CreateLinearDoubleHistogram(BorrowedStringValue name, double floor, |
| double step_size, |
| size_t buckets) __WARN_UNUSED_RESULT; |
| |
| // Create a new |ExponentialIntHistogram| with the given name and format that is a child of this |
| // node. If this node is not stored in a buffer, the created value will also not be stored in |
| // a buffer. |
| ExponentialIntHistogram CreateExponentialIntHistogram(BorrowedStringValue name, int64_t floor, |
| int64_t initial_step, |
| int64_t step_multiplier, |
| size_t buckets) __WARN_UNUSED_RESULT; |
| |
| // Create a new |ExponentialUintHistogram| with the given name and format that is a child of this |
| // node. If this node is not stored in a buffer, the created value will also not be stored in |
| // a buffer. |
| ExponentialUintHistogram CreateExponentialUintHistogram(BorrowedStringValue name, uint64_t floor, |
| uint64_t initial_step, |
| uint64_t step_multiplier, |
| size_t buckets) __WARN_UNUSED_RESULT; |
| |
| // Create a new |ExponentialDoubleHistogram| with the given name and format that is a child of |
| // this node. If this node is not stored in a buffer, the created value will also not be |
| // stored in a buffer. |
| ExponentialDoubleHistogram CreateExponentialDoubleHistogram(BorrowedStringValue name, |
| double floor, double initial_step, |
| double step_multiplier, |
| size_t buckets) __WARN_UNUSED_RESULT; |
| |
| // Create a new |LazyNode| with the given name that is populated by the given callback on demand. |
| // |
| // The passed |callback| will live as long as the returned LazyNode, and will not be called |
| // concurrently by multiple threads. |
| // |
| // For example: |
| // auto a = root.CreateChild("a"); |
| // a.CreateLazyNode("b", [] { |
| // Inspector insp; |
| // ValueList values; |
| // insp.GetRoot().CreateInt("val", 2, &values); |
| // return fpromise::make_ok_result(insp); |
| // }); |
| // |
| // Output: |
| // root: |
| // a: |
| // b: |
| // val = 2 |
| LazyNode CreateLazyNode(BorrowedStringValue name, |
| LazyNodeCallbackFn callback) __WARN_UNUSED_RESULT; |
| |
| // Create a new |LazyNode| with the given name that is a child of this node. |
| // The new child lifetime will be the same as the parent node. |
| void RecordLazyNode(BorrowedStringValue name, LazyNodeCallbackFn callback); |
| |
| // Same as CreateLazyNode, but emplaces the value in the given container. |
| // |
| // The type of |list| must have method emplace(LazyNode). |
| // inspect::ValueList is recommended for most use cases. |
| template <typename F, typename T> |
| void CreateLazyNode(BorrowedStringValue name, F callback, T* list) { |
| list->emplace(CreateLazyNode(name, std::move(callback))); |
| } |
| |
| // Create a new |LazyNode| with the given name that is a child of this node. |
| // The new child lifetime will be the same as the parent node. |
| void RecordLazyValues(BorrowedStringValue name, LazyNodeCallbackFn callback); |
| |
| // Create a new |LazyNode| whose children and properties are added to this node on demand. |
| // |
| // The passed |callback| will live as long as the returned LazyNode, and will not be called |
| // concurrently by multiple threads. |
| // |
| // The name is only used if inflating the tree callback fails. |
| // |
| // WARNING: It is the caller's responsibility to avoid name collisions with other properties |
| // on this node. |
| // |
| // For example: |
| // auto a = root.CreateChild("a"); |
| // a.CreateLazy("b", [] { |
| // Inspector insp; |
| // ValueList values; |
| // insp.GetRoot().CreateInt("val", 2).enlist(&values); |
| // return fpromise::make_ok_promise(insp); |
| // }); |
| // |
| // Output: |
| // root: |
| // a: |
| // val = 2 |
| // |
| // Alternatively: |
| // |
| // a.CreateLazyNode("b", [] { |
| // return fpromise::make_error_promise(); |
| // }); |
| // |
| // Possible output: |
| // root: |
| // a: |
| // b [Failed to open link] |
| LazyNode CreateLazyValues(BorrowedStringValue name, |
| LazyNodeCallbackFn callback) __WARN_UNUSED_RESULT; |
| |
| // Same as CreateLazyValues, but emplaces the value in the given container. |
| // |
| // The type of |list| must have method emplace(LazyNode). |
| // inspect::ValueList is recommended for most use cases. |
| template <typename F, typename T> |
| void CreateLazyValues(BorrowedStringValue name, F callback, T* list) { |
| list->emplace(CreateLazyValues(name, std::move(callback))); |
| } |
| |
| // Runs |callback| on this node. |
| // |
| // All operations performed by |callback| are guaranteed to appear in the same generation when |
| // reading Inspect data. |
| void AtomicUpdate(AtomicUpdateCallbackFn callback); |
| |
| // Return true if this node is stored in a buffer. False otherwise. |
| explicit operator bool() const { return state_ != nullptr; } |
| |
| // Create a unique name for children of this node. |
| // |
| // The returned strings are guaranteed to be at least unique within the context of this Node, |
| // except in the case that this is a default no-op node, in which case this always returns the |
| // empty string. |
| std::string UniqueName(const std::string& prefix); |
| |
| private: |
| friend class ::inspect::internal::State; |
| Node(std::shared_ptr<internal::State> state, internal::BlockIndex name, |
| internal::BlockIndex value) |
| : state_(std::move(state)), name_index_(name), value_index_(value) {} |
| |
| // Reference to the state containing this metric. |
| std::shared_ptr<internal::State> state_; |
| |
| // Index of the name block in the state. |
| internal::BlockIndex name_index_; |
| |
| // Index of the value block in the state. |
| internal::BlockIndex value_index_; |
| |
| // Internally stored values owned by this Node. |
| // |
| // Shared pointers are used so Node is copyable. |
| ValueList value_list_; |
| }; |
| |
| } // namespace inspect |
| |
| #endif // LIB_INSPECT_CPP_VMO_TYPES_H_ |