// Jackson Coxson #pragma once #include #include #include #include #include #include namespace IdeviceFFI { using SysmontapPtr = std::unique_ptr>; /// A sysmontap sample containing optional plist_t payloads. /// Non-null plists must be freed by the caller with plist_free(). struct SysmontapSample { /// Per-process data dict (pid → attribute array). May be null. plist_t processes = nullptr; /// System attribute array (order matches config's system_attributes). May be null. plist_t system = nullptr; /// CPU usage summary dict. May be null. plist_t system_cpu_usage = nullptr; }; class Sysmontap { public: static Result create(RemoteServer& server); /// Send configuration. Call before start(). Result set_config(uint32_t interval_ms, const std::vector& process_attributes, const std::vector& system_attributes); /// Starts sampling; consumes the device's initial ack internally. Result start(); Result stop(); /// Blocks until the next data row arrives. Result next_sample(); ~Sysmontap() noexcept = default; Sysmontap(Sysmontap&&) noexcept = default; Sysmontap& operator=(Sysmontap&&) noexcept = default; Sysmontap(const Sysmontap&) = delete; Sysmontap& operator=(const Sysmontap&) = delete; SysmontapHandle* raw() const noexcept { return handle_.get(); } static Sysmontap adopt(SysmontapHandle* h) noexcept { return Sysmontap(h); } private: explicit Sysmontap(SysmontapHandle* h) noexcept : handle_(h) {} SysmontapPtr handle_{}; }; } // namespace IdeviceFFI