/* * Copyright (c) 2018-2019 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #pragma once #include #include #include #include #include "ipc_service_object.hpp" class IDomainObject; class DomainManager { public: virtual std::shared_ptr AllocateDomain() = 0; virtual void FreeDomain(IDomainObject *domain) = 0; virtual Result ReserveObject(IDomainObject *domain, u32 *out_object_id) = 0; virtual Result ReserveSpecificObject(IDomainObject *domain, u32 object_id) = 0; virtual void SetObject(IDomainObject *domain, u32 object_id, ServiceObjectHolder&& holder) = 0; virtual ServiceObjectHolder *GetObject(IDomainObject *domain, u32 object_id) = 0; virtual Result FreeObject(IDomainObject *domain, u32 object_id) = 0; virtual Result ForceFreeObject(u32 object_id) = 0; }; class IDomainObject : public IServiceObject { private: DomainManager *manager; public: IDomainObject(DomainManager *m) : manager(m) {} virtual ~IDomainObject() override { this->manager->FreeDomain(this); } DomainManager *GetManager() { return this->manager; } ServiceObjectHolder *GetObject(u32 object_id) { return this->manager->GetObject(this, object_id); } Result ReserveObject(u32 *out_object_id) { return this->manager->ReserveObject(this, out_object_id); } Result ReserveSpecificObject(u32 object_id) { return this->manager->ReserveSpecificObject(this, object_id); } void SetObject(u32 object_id, ServiceObjectHolder&& holder) { this->manager->SetObject(this, object_id, std::move(holder)); } Result FreeObject(u32 object_id) { return this->manager->FreeObject(this, object_id); } Result ForceFreeObject(u32 object_id) { return this->manager->ForceFreeObject(object_id); } public: DEFINE_SERVICE_DISPATCH_TABLE { /* IDomainObject has no callable functions. */ }; }; static constexpr bool IsDomainObject(ServiceObjectHolder &holder) { return holder.GetServiceId() == ServiceObjectId(); } static constexpr bool IsDomainObject(ServiceObjectHolder *holder) { return holder->GetServiceId() == ServiceObjectId(); } /* Out for service impl. */ template class Out> : public OutSessionTag { static_assert(std::is_base_of_v, "OutSessions must be shared_ptr!"); template friend class Out; private: std::shared_ptr *srv; IDomainObject *domain = nullptr; u32 *object_id = nullptr; public: Out>(std::shared_ptr *s, IDomainObject *dm, u32 *o) : srv(reinterpret_cast *>(s)), domain(dm), object_id(o) { } ServiceObjectHolder GetHolder() { std::shared_ptr clone = *srv; return ServiceObjectHolder(std::move(clone)); } bool IsDomain() { return domain != nullptr; } u32 GetObjectId() { return *object_id; } void ChangeObjectId(u32 o) { domain->ForceFreeObject(*object_id); domain->ReserveSpecificObject(o); *object_id = o; } void SetValue(std::shared_ptr &&s) { *this->srv = std::move(s); } };