blob: 49994640d2586273bbaacf38475a9816e5ef4a08 [file] [log] [blame]
// 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_