| // Copyright 2019 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 SRC_TESTING_LOADBENCH_OBJECT_H_ |
| #define SRC_TESTING_LOADBENCH_OBJECT_H_ |
| |
| #include <lib/syslog/cpp/macros.h> |
| #include <lib/zx/channel.h> |
| #include <lib/zx/event.h> |
| #include <lib/zx/port.h> |
| #include <lib/zx/profile.h> |
| #include <lib/zx/time.h> |
| #include <lib/zx/timer.h> |
| |
| #include <string> |
| #include <unordered_map> |
| #include <utility> |
| #include <vector> |
| |
| // Abstract base for objects. |
| class Object { |
| public: |
| virtual ~Object() = default; |
| virtual zx_obj_type_t type() const = 0; |
| |
| static void CloseHandles() { handles_.clear(); } |
| |
| protected: |
| // Utility to create a zx::handle-based object. The actual handle is maintained in a static handle |
| // table for the lifetime of the workload. The return value is an unowned handle so that |
| // subclasses of Object that have handle members may be copiable. |
| template <typename T, typename... Args> |
| static zx::unowned<T> CreateHandle(Args&&... args) { |
| T result; |
| const auto status = T::create(std::forward<Args>(args)..., &result); |
| FX_CHECK(status == ZX_OK); |
| |
| const auto handle = result.release(); |
| handles_.emplace_back(handle); |
| |
| return zx::unowned<T>{handle}; |
| } |
| |
| // Similar to above for creating peered objects. |
| template <typename T, typename... Args> |
| static std::pair<zx::unowned<T>, zx::unowned<T>> CreateHandlePair(Args&&... args) { |
| std::pair<T, T> result; |
| const auto status = T::create(std::forward<Args>(args)..., &result.first, &result.second); |
| FX_CHECK(status == ZX_OK); |
| |
| const auto handle_first = result.first.release(); |
| handles_.emplace_back(handle_first); |
| |
| const auto handle_second = result.second.release(); |
| handles_.emplace_back(handle_second); |
| |
| return {zx::unowned<T>{handle_first}, zx::unowned<T>{handle_second}}; |
| } |
| |
| private: |
| inline static std::vector<zx::handle> handles_{}; |
| }; |
| |
| // CRTP type that provides common functionality for handle-based objects. ZxType must be an owned |
| // libzx object type (i.e. not an instantiation of zx::unowned<>). |
| template <typename T, typename ZxType> |
| class ObjectBase : public Object { |
| public: |
| using Base = ObjectBase; |
| inline static constexpr auto Type = ZxType::TYPE; |
| |
| ~ObjectBase() override {} |
| |
| zx_obj_type_t type() const override { return Type; } |
| |
| zx::unowned<ZxType>& operator->() { return object_; } |
| |
| zx::unowned<ZxType>& object() { return object_; } |
| zx::unowned<ZxType>& object() const { return object_; } |
| |
| template <typename... Args> |
| static std::unique_ptr<T> Create(Args&&... args) { |
| return std::make_unique<T>(std::forward<Args>(args)...); |
| } |
| |
| protected: |
| template <typename... Args> |
| ObjectBase(Args&&... args) : object_{CreateHandle<ZxType>(std::forward<Args>(args)...)} {} |
| |
| private: |
| zx::unowned<ZxType> object_; |
| }; |
| |
| template <typename T, typename ZxType> |
| class PairObjectBase : public Object { |
| public: |
| using Base = PairObjectBase; |
| inline static constexpr auto Type = ZxType::TYPE; |
| |
| ~PairObjectBase() override {} |
| |
| zx_obj_type_t type() const override { return Type; } |
| |
| auto* operator->() { return &objects_; } |
| |
| auto bind() { return std::tie(objects_.first, objects_.second); } |
| |
| template <typename... Args> |
| static std::unique_ptr<T> Create(Args&&... args) { |
| return std::make_unique<T>(std::forward<Args>(args)...); |
| } |
| |
| protected: |
| template <typename... Args> |
| PairObjectBase(Args&&... args) |
| : objects_{CreateHandlePair<ZxType>(std::forward<Args>(args)...)} {} |
| |
| private: |
| std::pair<zx::unowned<ZxType>, zx::unowned<ZxType>> objects_; |
| }; |
| |
| // Define objects. |
| struct EventObject : ObjectBase<EventObject, zx::event> { |
| EventObject(uint32_t options = 0) : Base{options} {} |
| }; |
| |
| struct TimerObject : ObjectBase<TimerObject, zx::timer> { |
| TimerObject() : Base{ZX_TIMER_SLACK_CENTER, ZX_CLOCK_MONOTONIC} {} |
| }; |
| |
| struct PortObject : ObjectBase<PortObject, zx::port> { |
| PortObject(uint32_t options = 0) : Base{options} {} |
| |
| static constexpr zx_signals_t kTerminateSignal = ZX_USER_SIGNAL_0; |
| |
| static zx::unowned_event GetTerminateEvent() { |
| static zx::unowned_event terminate_event{CreateHandle<zx::event>(0)}; |
| return zx::unowned_event{terminate_event->get()}; |
| } |
| }; |
| |
| struct ChannelObject : PairObjectBase<ChannelObject, zx::channel> { |
| ChannelObject(uint32_t options = 0) : Base{options} {} |
| }; |
| |
| #endif // SRC_TESTING_LOADBENCH_OBJECT_H_ |