123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- // Copyright 2018 The Chromium 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 BASE_TASK_TASK_TRAITS_EXTENSION_H_
- #define BASE_TASK_TASK_TRAITS_EXTENSION_H_
- #include <stdint.h>
- #include <array>
- #include <tuple>
- #include <utility>
- #include "base/base_export.h"
- #include "base/traits_bag.h"
- namespace base {
- // Embedders can attach additional traits to a TaskTraits object in a way that
- // is opaque to base. These extension traits can then be specified along the
- // base traits when constructing the TaskTraits object. They are then stored and
- // propagated with the TaskTraits object.
- //
- // To support constexpr-compatible construction, extension traits are stored in
- // a fixed-size byte array in the TaskTraits object and serialized into and
- // parsed from this storage by an embedder-provided extension class and
- // MakeTaskTraitsExtension() template function. The embedder can later access
- // the extension traits via TaskTraits::GetExtension<[ExtensionClass]>().
- //
- // A TaskTraits extension class needs to specify publicly:
- // (1) -- static constexpr uint8_t kExtensionId.
- // This field's value identifies the type of the extension uniquely within
- // each process. The embedder is responsible for ensuring uniqueness and
- // can assign values between kFirstEmbedderExtensionId and kMaxExtensionId
- // of TaskTraitsExtensionStorage::ExtensionId.
- // (2) -- static const [ExtensionClass] Parse(
- // -- const base::TaskTraitsExtensionStorage& extension).
- // Parses and constructs an extension object from the provided storage.
- //
- // For each TaskTraits extension class, the embedder has to provide a
- // corresponding MakeTaskTraitsExtension definition inside the same namespace
- // as its extension traits:
- // (3) -- template <...>
- // -- constexpr base::TaskTraitsExtensionStorage MakeTaskTraitsExtension(
- // -- ArgTypes... args).
- // Constructs and serializes an extension with the given arguments into
- // a TaskTraitsExtensionStorage and returns it. When the extension is used,
- // all traits, including the base ones, are passed to this function in
- // order make sure TaskTraits constructor only participates in overload
- // resolution if all traits are valid. As such, this function should only
- // accept valid task traits recognised by the extension and the base task
- // traits.
- //
- // EXAMPLE (see also base/task/test_task_traits_extension.h):
- // --------
- //
- // namespace my_embedder {
- // enum class MyExtensionTrait {kMyValue1, kMyValue2};
- //
- // class MyTaskTraitsExtension {
- // public:
- // static constexpr uint8_t kExtensionId =
- // TaskTraitsExtensionStorage::kFirstEmbedderExtensionId;
- //
- // struct ValidTrait : public TaskTraits::ValidTrait {
- // // Accept base traits in MakeTaskTraitsExtension (see above).
- // using TaskTraits::ValidTrait::ValidTrait;
- //
- // ValidTrait(MyExtensionTrait);
- // };
- //
- // using MyExtensionTraitFilter =
- // trait_helpers::EnumTraitFilter<MyExtensionTrait, MyExtensionTrait::kA>;
- //
- // // Constructor that accepts only valid traits as specified by ValidTraits.
- // template <class... ArgTypes,
- // class CheckArgumentsAreValid = std::enable_if_t<
- // base::trait_helpers::AreValidTraits<
- // ValidTrait, ArgTypes...>::value>>
- // constexpr MyTaskTraitsExtension(ArgTypes... args)
- // : my_trait_(trait_helpers::GetTraitFromArgList<MyExtensionTraitFilter>(
- // args...)) {}
- //
- // // Serializes MyTaskTraitsExtension into a storage object and returns it.
- // constexpr base::TaskTraitsExtensionStorage Serialize() const {
- // // Note: can't use reinterpret_cast or placement new because neither are
- // // constexpr-compatible.
- // return {kExtensionId, {{static_cast<uint8_t>(my_trait_)}}};
- // }
- //
- // // Creates a MyTaskTraitsExtension by parsing it from a storage object.
- // static const MyTaskTraitsExtension Parse(
- // const base::TaskTraitsExtensionStorage& extension) {
- // return MyTaskTraitsExtension(
- // static_cast<MyExtensionTrait>(extension.data[0]));
- // }
- //
- // constexpr MyExtensionTrait my_trait() const { return my_trait_; }
- //
- // private:
- // MyExtensionTrait my_trait_;
- // };
- //
- // // Creates a MyTaskTraitsExtension for the provided |args| and serializes it
- // // into |extension|. Accepts only valid arguments for the
- // // MyTaskTraitsExtension() constructor.
- // template <class... ArgTypes,
- // class = std::enable_if_t<
- // base::trait_helpers::AreValidTraits<
- // MyTaskTraitsExtension::ValidTrait, ArgTypes...>::value>>
- // constexpr base::TaskTraitsExtensionStorage MakeTaskTraitsExtension(
- // ArgTypes... args) {
- // return MyTaskTraitsExtension(args...).Serialize();
- // }
- // } // namespace my_embedder
- //
- // // Construction of TaskTraits with extension traits.
- // constexpr TaskTraits t1 = {my_embedder::MyExtensionTrait::kValueB};
- // constexpr TaskTraits t2 = {base::MayBlock(),
- // my_embedder::MyExtensionTrait::kValueA};
- //
- // // Extension traits can also be specified directly when posting a task.
- // base::PostTask(FROM_HERE,
- // {my_embedder::MyExtensionTrait::kValueB},
- // base::BindOnce(...));
- // Stores extension traits opaquely inside a fixed-size data array. We store
- // this data directly (rather than in a separate object on the heap) to support
- // constexpr-compatible TaskTraits construction.
- struct BASE_EXPORT TaskTraitsExtensionStorage {
- // Size in bytes.
- // Keep in sync with org.chromium.base.task.TaskTraits.EXTENSION_STORAGE_SIZE
- static constexpr size_t kStorageSize = 8;
- inline constexpr TaskTraitsExtensionStorage();
- inline constexpr TaskTraitsExtensionStorage(
- uint8_t extension_id_in,
- const std::array<uint8_t, kStorageSize>& data_in);
- inline constexpr TaskTraitsExtensionStorage(
- uint8_t extension_id_in,
- std::array<uint8_t, kStorageSize>&& data_in);
- inline constexpr TaskTraitsExtensionStorage(
- const TaskTraitsExtensionStorage& other);
- inline TaskTraitsExtensionStorage& operator=(
- const TaskTraitsExtensionStorage& other) = default;
- inline bool operator==(const TaskTraitsExtensionStorage& other) const;
- enum ExtensionId : uint8_t {
- // Keep in sync with org.chromium.base.task.TaskTraits.INVALID_EXTENSION_ID
- kInvalidExtensionId = 0,
- // The embedder is responsible for assigning the remaining values uniquely.
- kFirstEmbedderExtensionId = 1,
- // Maximum number of extension types is artificially limited to support
- // super efficient TaskExecutor lookup in post_task.cc.
- // Keep in sync with org.chromium.base.TaskTraits.MAX_EXTENSION_ID
- kMaxExtensionId = 4
- };
- // Identifies the type of extension. See ExtensionId enum above.
- uint8_t extension_id;
- // Serialized extension data.
- std::array<uint8_t, kStorageSize> data;
- };
- // TODO(https://crbug.com/874482): These constructors need to be "inline" but
- // defined outside the class above, because the chromium-style clang plugin
- // doesn't exempt constexpr constructors at the moment.
- inline constexpr TaskTraitsExtensionStorage::TaskTraitsExtensionStorage()
- : extension_id(kInvalidExtensionId), data{} {}
- inline constexpr TaskTraitsExtensionStorage::TaskTraitsExtensionStorage(
- uint8_t extension_id_in,
- const std::array<uint8_t, kStorageSize>& data_in)
- : extension_id(extension_id_in), data(data_in) {}
- inline constexpr TaskTraitsExtensionStorage::TaskTraitsExtensionStorage(
- uint8_t extension_id_in,
- std::array<uint8_t, kStorageSize>&& data_in)
- : extension_id(extension_id_in), data(std::move(data_in)) {}
- inline constexpr TaskTraitsExtensionStorage::TaskTraitsExtensionStorage(
- const TaskTraitsExtensionStorage& other) = default;
- namespace trait_helpers {
- // Helper class whose constructor tests if an extension accepts a list of
- // argument types.
- struct TaskTraitsExtension {
- template <class... ArgTypes,
- class CheckCanMakeExtension =
- decltype(MakeTaskTraitsExtension(std::declval<ArgTypes>()...))>
- constexpr TaskTraitsExtension(ArgTypes... args) {}
- };
- // Tests that that a trait extension accepts all |ArgsTypes...|.
- template <class... ArgTypes>
- using AreValidTraitsForExtension =
- std::is_constructible<TaskTraitsExtension, ArgTypes...>;
- // Helper function that returns the TaskTraitsExtensionStorage of a
- // serialized extension created with |args...| if there are arguments that are
- // not valid base traits, or a default constructed TaskTraitsExtensionStorage
- // otherwise.
- template <class... ArgTypes>
- constexpr TaskTraitsExtensionStorage GetTaskTraitsExtension(
- std::true_type base_traits,
- ArgTypes... args) {
- return TaskTraitsExtensionStorage();
- }
- template <class... ArgTypes>
- constexpr TaskTraitsExtensionStorage GetTaskTraitsExtension(
- std::false_type base_traits,
- ArgTypes... args) {
- return MakeTaskTraitsExtension(args...);
- }
- } // namespace trait_helpers
- // TODO(eseckler): Default the comparison operator once C++20 arrives.
- inline bool TaskTraitsExtensionStorage::operator==(
- const TaskTraitsExtensionStorage& other) const {
- static_assert(
- 9 == sizeof(TaskTraitsExtensionStorage),
- "Update comparison operator when TaskTraitsExtensionStorage changes");
- return extension_id == other.extension_id && data == other.data;
- }
- } // namespace base
- #endif // BASE_TASK_TASK_TRAITS_EXTENSION_H_
|