libstrat: convert to experimental new (super-accurate) sf allocation semantics
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/sf/impl/sf_impl_autogen_interface_macros.hpp>
|
||||
#include <stratosphere/sf/impl/sf_impl_template_base.hpp>
|
||||
|
||||
namespace ams::sf::impl {
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_IMPL_SYNC_METHOD(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
virtual RETURN AMS_SF_IMPL_SYNC_FUNCTION_NAME(NAME) ARGS override { \
|
||||
return ImplGetter::GetImplPointer(static_cast<ImplHolder *>(this))->NAME ARGNAMES; \
|
||||
}
|
||||
|
||||
#define AMS_SF_DEFINE_INTERFACE(NAMESPACE, INTERFACE, CMD_MACRO) \
|
||||
namespace NAMESPACE { \
|
||||
\
|
||||
AMS_SF_DEFINE_INTERFACE_IMPL(::ams::sf::IServiceObject, INTERFACE, CMD_MACRO) \
|
||||
\
|
||||
} \
|
||||
\
|
||||
namespace ams::sf::impl { \
|
||||
\
|
||||
template<typename Base, typename ImplHolder, typename ImplGetter, typename Root> \
|
||||
class ImplTemplateBaseT<::NAMESPACE::INTERFACE, Base, ImplHolder, ImplGetter, Root> : public Base, public ImplHolder { \
|
||||
public: \
|
||||
template<typename... Args> \
|
||||
constexpr explicit ImplTemplateBaseT(Args &&...args) : ImplHolder(std::forward<Args>(args)...) { /* ... */ } \
|
||||
private: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_IMPL_SYNC_METHOD) \
|
||||
}; \
|
||||
\
|
||||
}
|
||||
|
||||
#define AMS_SF_DEFINE_INTERFACE_WITH_BASE(NAMESPACE, INTERFACE, BASE, CMD_MACRO) \
|
||||
namespace NAMESPACE { \
|
||||
\
|
||||
AMS_SF_DEFINE_INTERFACE_IMPL(BASE, INTERFACE, CMD_MACRO) \
|
||||
\
|
||||
} \
|
||||
\
|
||||
namespace ams::sf::impl { \
|
||||
\
|
||||
template<typename Base, typename ImplHolder, typename ImplGetter, typename Root> \
|
||||
class ImplTemplateBaseT<::NAMESPACE::INTERFACE, Base, ImplHolder, ImplGetter, Root> : public ImplTemplateBaseT<BASE, Base, ImplHolder, ImplGetter, Root> { \
|
||||
private: \
|
||||
using BaseImplTemplateBase = ImplTemplateBaseT<BASE, Base, ImplHolder, ImplGetter, Root>; \
|
||||
public: \
|
||||
template<typename... Args> \
|
||||
constexpr explicit ImplTemplateBaseT(Args &&...args) : BaseImplTemplateBase(std::forward<Args>(args)...) { /* ... */ } \
|
||||
private: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_IMPL_SYNC_METHOD) \
|
||||
}; \
|
||||
\
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::sf::impl {
|
||||
|
||||
struct SyncFunctionTraits {
|
||||
public:
|
||||
template<typename R, typename C, typename... A>
|
||||
static std::tuple<A...> GetArgsImpl(R(C::*)(A...));
|
||||
};
|
||||
|
||||
template<auto F>
|
||||
using SyncFunctionArgsType = decltype(SyncFunctionTraits::GetArgsImpl(F));
|
||||
|
||||
template<typename T>
|
||||
struct TypeTag{};
|
||||
|
||||
template<size_t First, size_t... Ix>
|
||||
static constexpr inline size_t ParameterCount = sizeof...(Ix);
|
||||
|
||||
#define AMS_SF_IMPL_SYNC_FUNCTION_NAME(FUNCNAME) \
|
||||
_ams_sf_sync_##FUNCNAME
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_INTERFACE_SYNC_METHOD(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
virtual RETURN AMS_SF_IMPL_SYNC_FUNCTION_NAME(NAME) ARGS = 0;
|
||||
|
||||
#define AMS_SF_IMPL_EXTRACT_INTERFACE_SYNC_METHOD_ARGUMENTS(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
using NAME##ArgumentsType = ::ams::sf::impl::SyncFunctionArgsType<&CLASSNAME::AMS_SF_IMPL_SYNC_FUNCTION_NAME(NAME)>;
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_INTERFACE_METHOD(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
ALWAYS_INLINE RETURN NAME ARGS { \
|
||||
return this->AMS_SF_IMPL_SYNC_FUNCTION_NAME(NAME) ARGNAMES; \
|
||||
}
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_INTERFACE_SERVICE_COMMAND_META_HOLDER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
template<typename Interface, typename A> struct NAME##ServiceCommandMetaHolder; \
|
||||
\
|
||||
template<typename Interface, typename ...Arguments> \
|
||||
requires std::same_as<std::tuple<Arguments...>, NAME##ArgumentsType> \
|
||||
struct NAME##ServiceCommandMetaHolder<Interface, std::tuple<Arguments...>> { \
|
||||
static constexpr auto Value = ::ams::sf::impl::MakeServiceCommandMeta<VERSION_MIN, VERSION_MAX, CMD_ID, &Interface::AMS_SF_IMPL_SYNC_FUNCTION_NAME(NAME), RETURN, Interface, Arguments...>(); \
|
||||
};
|
||||
|
||||
#define AMS_SF_IMPL_GET_NULL_FOR_PARAMETER_COUNT(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
, 0
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_CMIF_SERVICE_COMMAND_META_TABLE_ENTRY(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
NAME##ServiceCommandMetaHolder<Interface, NAME##ArgumentsType>::Value,
|
||||
|
||||
template<typename...>
|
||||
struct Print;
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_INTERFACE(BASECLASS, CLASSNAME, CMD_MACRO) \
|
||||
class CLASSNAME : public BASECLASS { \
|
||||
private: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_INTERFACE_SYNC_METHOD) \
|
||||
public: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_EXTRACT_INTERFACE_SYNC_METHOD_ARGUMENTS) \
|
||||
public: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_INTERFACE_METHOD) \
|
||||
private: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_INTERFACE_SERVICE_COMMAND_META_HOLDER) \
|
||||
public: \
|
||||
template<typename Interface> \
|
||||
static constexpr inline ::ams::sf::cmif::ServiceDispatchTable s_CmifServiceDispatchTable { \
|
||||
[] { \
|
||||
constexpr size_t CurSize = ::ams::sf::impl::ParameterCount<0 CMD_MACRO(CLASSNAME, AMS_SF_IMPL_GET_NULL_FOR_PARAMETER_COUNT) >; \
|
||||
std::array<::ams::sf::cmif::ServiceCommandMeta, CurSize> cur_entries { CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_CMIF_SERVICE_COMMAND_META_TABLE_ENTRY) }; \
|
||||
\
|
||||
constexpr const auto &BaseEntries = ::ams::sf::cmif::ServiceDispatchTraits<BASECLASS>::DispatchTable.GetEntries(); \
|
||||
constexpr size_t BaseSize = BaseEntries.size(); \
|
||||
\
|
||||
std::array<::ams::sf::cmif::ServiceCommandMeta, BaseSize + CurSize> combined_entries{}; \
|
||||
for (size_t i = 0; i < BaseSize; ++i) { \
|
||||
combined_entries[i] = BaseEntries[i]; \
|
||||
} \
|
||||
for (size_t i = 0; i < CurSize; ++i) { \
|
||||
combined_entries[BaseSize + i] = cur_entries[i]; \
|
||||
} \
|
||||
\
|
||||
return ::ams::sf::cmif::ServiceDispatchTable { combined_entries }; \
|
||||
} () \
|
||||
}; \
|
||||
};
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_CONCEPT_HELPERS(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
template<typename T, typename... Args> \
|
||||
concept Is##CLASSNAME##__##NAME##Impl = requires (T &t, Args &&... args) { \
|
||||
{ t.NAME(std::forward<Args>(args)...) } -> std::same_as<RETURN>; \
|
||||
}; \
|
||||
\
|
||||
template<typename T, typename A> \
|
||||
struct Is##CLASSNAME##__##NAME##Holder : std::false_type{}; \
|
||||
\
|
||||
template<typename T, typename... Args> requires std::same_as<std::tuple<Args...>, CLASSNAME::NAME##ArgumentsType> \
|
||||
struct Is##CLASSNAME##__##NAME##Holder<T, std::tuple<Args...>> : std::bool_constant<Is##CLASSNAME##__##NAME##Impl<T, Args...>>{}; \
|
||||
\
|
||||
template<typename T> \
|
||||
static constexpr inline bool Is##CLASSNAME##__##NAME = Is##CLASSNAME##__##NAME##Holder<T, CLASSNAME::NAME##ArgumentsType>::value;
|
||||
|
||||
#define AMS_SF_IMPL_CHECK_CONCEPT_HELPER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
Is##CLASSNAME##__##NAME<T> &&
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_CONCEPT(CLASSNAME, CMD_MACRO) \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_CONCEPT_HELPERS) \
|
||||
\
|
||||
template<typename T> \
|
||||
concept Is##CLASSNAME = CMD_MACRO(CLASSNAME, AMS_SF_IMPL_CHECK_CONCEPT_HELPER) true;
|
||||
|
||||
#define AMS_SF_DEFINE_INTERFACE_IMPL(BASECLASS, CLASSNAME, CMD_MACRO) \
|
||||
AMS_SF_IMPL_DEFINE_INTERFACE(::ams::sf::IServiceObject, CLASSNAME, CMD_MACRO) \
|
||||
AMS_SF_IMPL_DEFINE_CONCEPT(CLASSNAME, CMD_MACRO) \
|
||||
static_assert(Is##CLASSNAME<CLASSNAME>);
|
||||
|
||||
#define AMS_SF_METHOD_INFO_7(CLASSNAME, HANDLER, CMD_ID, RETURN, NAME, ARGS, ARGNAMES) \
|
||||
HANDLER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, hos::Version_Min, hos::Version_Max)
|
||||
|
||||
#define AMS_SF_METHOD_INFO_8(CLASSNAME, HANDLER, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN) \
|
||||
HANDLER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, hos::Version_Max)
|
||||
|
||||
#define AMS_SF_METHOD_INFO_9(CLASSNAME, HANDLER, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
HANDLER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX)
|
||||
|
||||
#define AMS_SF_METHOD_INFO_X(_, _0, _1, _2, _3, _4, _5, _6, _7, _8, FUNC, ...) FUNC
|
||||
|
||||
#define AMS_SF_METHOD_INFO(...) \
|
||||
AMS_SF_METHOD_INFO_X(, ## __VA_ARGS__, AMS_SF_METHOD_INFO_9(__VA_ARGS__), AMS_SF_METHOD_INFO_8(__VA_ARGS__), AMS_SF_METHOD_INFO_7(__VA_ARGS__))
|
||||
|
||||
}
|
||||
@@ -68,34 +68,78 @@ namespace ams::sf {
|
||||
|
||||
struct OutObjectTag{};
|
||||
|
||||
template<size_t, size_t>
|
||||
class InOutObjectHolder;
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class IsOutForceEnabled<std::shared_ptr<T>> : public std::true_type{};
|
||||
|
||||
template<typename ServiceImpl>
|
||||
class Out<std::shared_ptr<ServiceImpl>> : public impl::OutObjectTag {
|
||||
static_assert(std::is_base_of<sf::IServiceObject, ServiceImpl>::value, "Out<std::shared_ptr<ServiceImpl>> requires ServiceObject base.");
|
||||
|
||||
template<typename ServiceImpl> requires std::derived_from<ServiceImpl, IServiceObject>
|
||||
class Out<SharedPointer<ServiceImpl>> : public impl::OutObjectTag {
|
||||
template<typename>
|
||||
friend class Out;
|
||||
|
||||
public:
|
||||
using ServiceImplType = ServiceImpl;
|
||||
using Interface = ServiceImpl;
|
||||
private:
|
||||
cmif::ServiceObjectHolder *srv;
|
||||
cmif::DomainObjectId *object_id;
|
||||
impl::SharedPointerBase *m_out;
|
||||
cmif::DomainObjectId *m_object_id;
|
||||
private:
|
||||
Out(impl::SharedPointerBase *p, cmif::DomainObjectId *o = nullptr) : m_out(p), m_object_id(o) { /* ... */ }
|
||||
public:
|
||||
Out(cmif::ServiceObjectHolder *s) : srv(s), object_id(nullptr) { /* ... */ }
|
||||
Out(cmif::ServiceObjectHolder *s, cmif::DomainObjectId *o) : srv(s), object_id(o) { /* ... */ }
|
||||
Out(const Out &rhs) : m_out(rhs.m_out), m_object_id(rhs.m_object_id) { /* ... */ }
|
||||
|
||||
void SetValue(std::shared_ptr<ServiceImpl> &&s, cmif::DomainObjectId new_object_id = cmif::InvalidDomainObjectId) {
|
||||
*this->srv = cmif::ServiceObjectHolder(std::move(s));
|
||||
Out(SharedPointer<ServiceImpl> *out, cmif::DomainObjectId *o = nullptr) : m_out(std::addressof(out->m_base)), m_object_id(o) { /* .... */ }
|
||||
|
||||
template<typename U> requires std::derived_from<U, ServiceImpl>
|
||||
Out(Out<SharedPointer<U>> out) : m_out(out.m_out), m_object_id(out.m_object_id) { /* ... */ }
|
||||
|
||||
template<typename U> requires std::derived_from<U, ServiceImpl>
|
||||
Out(SharedPointer<U> *out, cmif::DomainObjectId *o = nullptr) : m_out(std::addressof(out->m_base)), m_object_id(o) { /* .... */ }
|
||||
|
||||
void SetValue(SharedPointer<ServiceImpl> s, cmif::DomainObjectId new_object_id = cmif::InvalidDomainObjectId) {
|
||||
*m_out = std::move(s.m_base);
|
||||
if (new_object_id != cmif::InvalidDomainObjectId) {
|
||||
AMS_ABORT_UNLESS(object_id != nullptr);
|
||||
*this->object_id = new_object_id;
|
||||
AMS_ABORT_UNLESS(m_object_id != nullptr);
|
||||
*m_object_id = new_object_id;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename U> requires std::derived_from<U, ServiceImpl>
|
||||
void SetValue(SharedPointer<U> s, cmif::DomainObjectId new_object_id = cmif::InvalidDomainObjectId) {
|
||||
*m_out = std::move(s.m_base);
|
||||
if (new_object_id != cmif::InvalidDomainObjectId) {
|
||||
AMS_ABORT_UNLESS(m_object_id != nullptr);
|
||||
*m_object_id = new_object_id;
|
||||
}
|
||||
}
|
||||
|
||||
class DerefProxy {
|
||||
template<typename>
|
||||
friend class Out;
|
||||
private:
|
||||
Out &m_target;
|
||||
private:
|
||||
explicit DerefProxy(Out &t) : m_target(t) { /* ... */ }
|
||||
public:
|
||||
DerefProxy &operator=(SharedPointer<ServiceImpl> p) {
|
||||
m_target.SetValue(std::move(p));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename U> requires std::derived_from<U, ServiceImpl>
|
||||
DerefProxy &operator=(SharedPointer<U> p) {
|
||||
m_target.SetValue(std::move(p));
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
DerefProxy operator *() {
|
||||
return DerefProxy(*this);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
Out<SharedPointer<U>> DownCast() {
|
||||
return Out<SharedPointer<U>>(m_out, m_object_id);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -149,8 +193,8 @@ namespace ams::sf::impl {
|
||||
struct IsInObject : public std::false_type{};
|
||||
|
||||
template<typename T>
|
||||
struct IsInObject<std::shared_ptr<T>> : public std::true_type {
|
||||
static_assert(std::is_base_of<sf::IServiceObject, T>::value, "Invalid IsInObject<std::shared_ptr<T>>");
|
||||
struct IsInObject<sf::SharedPointer<T>> : public std::true_type {
|
||||
static_assert(std::is_base_of<sf::IServiceObject, T>::value, "Invalid IsInObject<sf::SharedPointer<T>>");
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@@ -628,6 +672,7 @@ namespace ams::sf::impl {
|
||||
private:
|
||||
std::array<cmif::ServiceObjectHolder, NumInObjects> in_object_holders;
|
||||
std::array<cmif::ServiceObjectHolder, NumOutObjects> out_object_holders;
|
||||
std::array<TYPED_STORAGE(SharedPointer<sf::IServiceObject>), NumOutObjects> out_shared_pointers;
|
||||
std::array<cmif::DomainObjectId, NumOutObjects> out_object_ids;
|
||||
public:
|
||||
constexpr InOutObjectHolder() : in_object_holders(), out_object_holders() {
|
||||
@@ -655,8 +700,8 @@ namespace ams::sf::impl {
|
||||
static_assert(std::tuple_size<ServiceImplTuple>::value == NumInObjects);
|
||||
#define _SF_IN_OUT_HOLDER_VALIDATE_IN_OBJECT(n) do { \
|
||||
if constexpr (NumInObjects > n) { \
|
||||
using SharedPtrToServiceImplType = typename std::tuple_element<n, ServiceImplTuple>::type; \
|
||||
using ServiceImplType = typename SharedPtrToServiceImplType::element_type; \
|
||||
using SharedPointerType = typename std::tuple_element<n, ServiceImplTuple>::type; \
|
||||
using ServiceImplType = typename SharedPointerType::Interface; \
|
||||
R_UNLESS((this->in_object_holders[n].template IsServiceObjectValid<ServiceImplType>()), sf::cmif::ResultInvalidInObject()); \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -672,15 +717,21 @@ namespace ams::sf::impl {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
template<size_t Index, typename ServiceImpl>
|
||||
std::shared_ptr<ServiceImpl> GetInObject() const {
|
||||
/* We know from ValidateInObjects() that this will succeed always. */
|
||||
return this->in_object_holders[Index].template GetServiceObject<ServiceImpl>();
|
||||
template<size_t Index, typename Interface>
|
||||
SharedPointer<Interface> *GetOutObjectSharedPointer() {
|
||||
static_assert(sizeof(SharedPointer<Interface>) == sizeof(SharedPointer<sf::IServiceObject>));
|
||||
return static_cast<SharedPointer<Interface> *>(static_cast<void *>(&out_shared_pointers[Index]));
|
||||
}
|
||||
|
||||
template<size_t Index, typename ServiceImpl>
|
||||
Out<std::shared_ptr<ServiceImpl>> GetOutObject() {
|
||||
return Out<std::shared_ptr<ServiceImpl>>(&this->out_object_holders[Index], &this->out_object_ids[Index]);
|
||||
template<size_t Index, typename Interface>
|
||||
Out<SharedPointer<Interface>> GetOutObject() {
|
||||
auto sp = new (GetOutObjectSharedPointer<Index, Interface>()) SharedPointer<Interface>;
|
||||
return Out<SharedPointer<Interface>>(sp, &this->out_object_ids[Index]);
|
||||
}
|
||||
|
||||
template<size_t Index, typename Interface>
|
||||
void SetOutObject() {
|
||||
this->out_object_holders[Index] = cmif::ServiceObjectHolder(std::move(*GetOutObjectSharedPointer<Index, Interface>()));
|
||||
}
|
||||
|
||||
constexpr void SetOutObjects(const cmif::ServiceDispatchContext &ctx, const HipcRequest &response) {
|
||||
@@ -985,10 +1036,10 @@ namespace ams::sf::impl {
|
||||
}
|
||||
} else if constexpr (Info.arg_type == ArgumentType::InObject) {
|
||||
/* New InObject. */
|
||||
return in_out_objects_holder.template GetInObject<Info.in_object_index, typename T::element_type>();
|
||||
return in_out_objects_holder.template GetInObject<Info.in_object_index, typename T::Interface>();
|
||||
} else if constexpr (Info.arg_type == ArgumentType::OutObject) {
|
||||
/* New OutObject. */
|
||||
return in_out_objects_holder.template GetOutObject<Info.out_object_index, typename T::ServiceImplType>();
|
||||
return in_out_objects_holder.template GetOutObject<Info.out_object_index, typename T::Interface>();
|
||||
} else if constexpr (Info.arg_type == ArgumentType::Buffer) {
|
||||
/* Buffers were already processed earlier. */
|
||||
if constexpr (sf::IsLargeData<T>) {
|
||||
@@ -1124,6 +1175,21 @@ namespace ams::sf::impl {
|
||||
out_handles_holder.CopyTo(response, runtime_metadata.GetOutObjectCount());
|
||||
|
||||
/* Set output objects. */
|
||||
#define _SF_IMPL_PROCESSOR_MARSHAL_OUT_OBJECT(n) do { \
|
||||
if constexpr (n < CommandMeta::NumOutObjects) { \
|
||||
in_out_objects_holder.template SetOutObject<n, typename std::tuple_element_t<n, typename CommandMeta::OutObjects>::Interface>(); \
|
||||
} \
|
||||
} while (0)
|
||||
_SF_IMPL_PROCESSOR_MARSHAL_OUT_OBJECT(0);
|
||||
_SF_IMPL_PROCESSOR_MARSHAL_OUT_OBJECT(1);
|
||||
_SF_IMPL_PROCESSOR_MARSHAL_OUT_OBJECT(2);
|
||||
_SF_IMPL_PROCESSOR_MARSHAL_OUT_OBJECT(3);
|
||||
_SF_IMPL_PROCESSOR_MARSHAL_OUT_OBJECT(4);
|
||||
_SF_IMPL_PROCESSOR_MARSHAL_OUT_OBJECT(5);
|
||||
_SF_IMPL_PROCESSOR_MARSHAL_OUT_OBJECT(6);
|
||||
_SF_IMPL_PROCESSOR_MARSHAL_OUT_OBJECT(7);
|
||||
_SF_IMPL_PROCESSOR_MARSHAL_OUT_OBJECT(8);
|
||||
#undef _SF_IMPL_PROCESSOR_MARSHAL_OUT_OBJECT
|
||||
in_out_objects_holder.SetOutObjects(ctx, response);
|
||||
|
||||
return ResultSuccess();
|
||||
|
||||
@@ -1,327 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::sf::impl {
|
||||
|
||||
template<typename T>
|
||||
concept ServiceCommandResult = std::same_as<::ams::Result, T> || std::same_as<void, T>;
|
||||
|
||||
template<auto F, typename ...Arguments>
|
||||
concept Invokable = requires (Arguments &&... args) {
|
||||
{ F(std::forward<Arguments>(args)...) };
|
||||
};
|
||||
|
||||
struct FunctionTraits {
|
||||
public:
|
||||
template<typename R, typename... A>
|
||||
static std::tuple<A...> GetArgsImpl(R(A...));
|
||||
};
|
||||
|
||||
template<auto F>
|
||||
using FunctionArgsType = decltype(FunctionTraits::GetArgsImpl(F));
|
||||
|
||||
template<typename Class, typename Return, typename ArgsTuple>
|
||||
struct ClassFunctionPointerHelper;
|
||||
|
||||
template<typename Class, typename Return, typename... Arguments>
|
||||
struct ClassFunctionPointerHelper<Class, Return, std::tuple<Arguments...>> {
|
||||
using Type = Return (*)(Class *, Arguments &&...);
|
||||
};
|
||||
|
||||
template<typename Class, typename Return, typename ArgsTuple>
|
||||
using ClassFunctionPointer = typename ClassFunctionPointerHelper<Class, Return, ArgsTuple>::Type;
|
||||
|
||||
template<typename T>
|
||||
struct TypeTag{};
|
||||
|
||||
#define AMS_SF_IMPL_HELPER_FUNCTION_NAME_IMPL(CLASSNAME, FUNCNAME, SUFFIX) \
|
||||
__ams_sf_impl_helper_##CLASSNAME##_##FUNCNAME##_##SUFFIX
|
||||
|
||||
#define AMS_SF_IMPL_HELPER_FUNCTION_NAME(CLASSNAME, FUNCNAME) \
|
||||
AMS_SF_IMPL_HELPER_FUNCTION_NAME_IMPL(CLASSNAME, FUNCNAME, intf)
|
||||
|
||||
#define AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, FUNCNAME) \
|
||||
::ams::sf::impl::FunctionArgsType<AMS_SF_IMPL_HELPER_FUNCTION_NAME(CLASSNAME, FUNCNAME)>
|
||||
|
||||
#define AMS_SF_IMPL_CONCEPT_HELPER_FUNCTION_NAME(CLASSNAME, FUNCNAME) \
|
||||
AMS_SF_IMPL_HELPER_FUNCTION_NAME_IMPL(CLASSNAME, FUNCNAME, intf_for_concept)
|
||||
|
||||
#define AMS_SF_IMPL_DECLARE_HELPER_FUNCTIONS(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
static void AMS_SF_IMPL_HELPER_FUNCTION_NAME(CLASSNAME, NAME) ARGS { __builtin_unreachable(); } \
|
||||
template<typename T, typename... Arguments> \
|
||||
requires std::same_as<std::tuple<Arguments...>, AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)> \
|
||||
static auto AMS_SF_IMPL_CONCEPT_HELPER_FUNCTION_NAME(CLASSNAME, NAME) (T &t, std::tuple<Arguments...> a) { \
|
||||
return [&]<size_t... Ix>(std::index_sequence<Ix...>) { \
|
||||
return t.NAME(std::forward<typename std::tuple_element<Ix, decltype(a)>::type>(std::get<Ix>(a))...); \
|
||||
}(std::make_index_sequence<sizeof...(Arguments)>()); \
|
||||
}
|
||||
|
||||
#define AMS_SF_IMPL_DECLARE_HELPERS(CLASSNAME, CMD_MACRO) \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DECLARE_HELPER_FUNCTIONS)
|
||||
|
||||
#define AMS_SF_IMPL_DECLARE_CONCEPT_REQUIREMENT(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
{ AMS_SF_IMPL_CONCEPT_HELPER_FUNCTION_NAME(CLASSNAME, NAME) (impl, std::declval<AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)>()) } -> ::ams::sf::impl::ServiceCommandResult;
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_CONCEPT(CLASSNAME, CMD_MACRO) \
|
||||
template<typename Impl> \
|
||||
concept Is##CLASSNAME = requires (Impl &impl) { \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DECLARE_CONCEPT_REQUIREMENT) \
|
||||
};
|
||||
|
||||
#define AMS_SF_IMPL_FUNCTION_POINTER_TYPE(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
::ams::sf::impl::ClassFunctionPointer<CLASSNAME, RETURN, AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)>
|
||||
|
||||
#define AMS_SF_IMPL_DECLARE_FUNCTION_POINTER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
AMS_SF_IMPL_FUNCTION_POINTER_TYPE(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) NAME;
|
||||
|
||||
#define AMS_SF_IMPL_DECLARE_INTERFACE_FUNCTION(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
template<typename ...Arguments> \
|
||||
requires std::same_as<std::tuple<Arguments...>, AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)> \
|
||||
RETURN Invoke##NAME##ByCommandTable (Arguments &&... args) { \
|
||||
return this->cmd_table->NAME(this, std::forward<Arguments>(args)...); \
|
||||
} \
|
||||
template<typename ...Arguments> \
|
||||
requires (::ams::sf::impl::Invokable<AMS_SF_IMPL_HELPER_FUNCTION_NAME(CLASSNAME, NAME), Arguments...> && \
|
||||
std::same_as<std::tuple<Arguments...>, AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)>) \
|
||||
ALWAYS_INLINE RETURN NAME (Arguments &&... args) { \
|
||||
return this->Invoke##NAME##ByCommandTable(std::forward<Arguments>(args)...); \
|
||||
} \
|
||||
template<typename ...Arguments> \
|
||||
requires (::ams::sf::impl::Invokable<AMS_SF_IMPL_HELPER_FUNCTION_NAME(CLASSNAME, NAME), Arguments...> && \
|
||||
!std::same_as<std::tuple<Arguments...>, AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)>) \
|
||||
ALWAYS_INLINE RETURN NAME (Arguments &&... args) { \
|
||||
return [this] <typename... CorrectArguments, typename... PassedArguments> ALWAYS_INLINE_LAMBDA (::ams::sf::impl::TypeTag<std::tuple<CorrectArguments...>>, PassedArguments &&...args_) -> RETURN { \
|
||||
return this->template NAME<CorrectArguments...>(std::forward<CorrectArguments>(args_)...); \
|
||||
}(::ams::sf::impl::TypeTag<AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)>{}, std::forward<Arguments>(args)...); \
|
||||
}
|
||||
|
||||
#define AMS_SF_IMPL_DECLARE_INTERFACE_FUNCTION_INVOKER_HOLDER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
template<typename ...Arguments> \
|
||||
requires std::same_as<std::tuple<Arguments...>, AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)> \
|
||||
static RETURN NAME##Invoker (CLASSNAME *_this, Arguments &&... args) { \
|
||||
return static_cast<ImplHolder *>(_this)->NAME(std::forward<Arguments>(args)...); \
|
||||
}
|
||||
|
||||
#define AMS_SF_IMPL_DECLARE_INTERFACE_FUNCTION_INVOKER_POINTER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
template<typename ...Arguments> \
|
||||
requires std::same_as<std::tuple<Arguments...>, AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)> \
|
||||
static RETURN NAME##Invoker (CLASSNAME *_this, Arguments &&... args) { \
|
||||
return static_cast<ImplPointer *>(_this)->NAME(std::forward<Arguments>(args)...); \
|
||||
}
|
||||
|
||||
#define AMS_SF_IMPL_DECLARE_INTERFACE_FUNCTION_INVOKER_SHARED_POINTER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
template<typename ...Arguments> \
|
||||
requires std::same_as<std::tuple<Arguments...>, AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)> \
|
||||
static RETURN NAME##Invoker (CLASSNAME *_this, Arguments &&... args) { \
|
||||
return static_cast<ImplSharedPointer *>(_this)->NAME(std::forward<Arguments>(args)...); \
|
||||
}
|
||||
|
||||
#define AMS_SF_IMPL_DECLARE_INTERFACE_FUNCTION_IMPL(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
template<typename ...Arguments> \
|
||||
requires (std::same_as<std::tuple<Arguments...>, AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)> && \
|
||||
std::same_as<RETURN, decltype(impl.NAME(std::declval<Arguments>()...))>) \
|
||||
RETURN NAME (Arguments &&... args) { \
|
||||
return this->impl.NAME(std::forward<Arguments>(args)...); \
|
||||
}
|
||||
|
||||
#define AMS_SF_IMPL_DECLARE_INTERFACE_FUNCTION_IMPL_PTR(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
template<typename ...Arguments> \
|
||||
requires (std::same_as<std::tuple<Arguments...>, AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)> && \
|
||||
std::same_as<RETURN, decltype(impl->NAME(std::declval<Arguments>()...))>) \
|
||||
RETURN NAME (Arguments &&... args) { \
|
||||
return this->impl->NAME(std::forward<Arguments>(args)...); \
|
||||
}
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_INTERFACE_IMPL_FUNCTION_POINTER_HOLDER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
template<typename A> struct NAME##FunctionPointerHolder; \
|
||||
\
|
||||
template<typename ...Arguments> \
|
||||
requires std::same_as<std::tuple<Arguments...>, AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)> \
|
||||
struct NAME##FunctionPointerHolder<std::tuple<Arguments...>> { \
|
||||
static constexpr auto Value = static_cast<AMS_SF_IMPL_FUNCTION_POINTER_TYPE(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX)>(&NAME##Invoker<Arguments...>); \
|
||||
};
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_INTERFACE_SERVICE_COMMAND_META_HOLDER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
template<typename ServiceImpl, typename A> struct NAME##ServiceCommandMetaHolder; \
|
||||
\
|
||||
template<typename ServiceImpl, typename ...Arguments> \
|
||||
requires std::same_as<std::tuple<Arguments...>, AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)> \
|
||||
struct NAME##ServiceCommandMetaHolder<ServiceImpl, std::tuple<Arguments...>> { \
|
||||
static constexpr auto Value = ::ams::sf::impl::MakeServiceCommandMeta<VERSION_MIN, VERSION_MAX, CMD_ID, &ServiceImpl::template Invoke##NAME##ByCommandTable<Arguments...>, RETURN, CLASSNAME, Arguments...>(); \
|
||||
};
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_INTERFACE_COMMAND_POINTER_TABLE_MEMBER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
.NAME = NAME##FunctionPointerHolder<AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)>::Value,
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_CMIF_SERVICE_COMMAND_META_TABLE_ENTRY(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
NAME##ServiceCommandMetaHolder<ServiceImpl, AMS_SF_IMPL_HELPER_FUNCTION_ARGS(CLASSNAME, NAME)>::Value,
|
||||
|
||||
template<typename T>
|
||||
struct Print;
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_CLASS(BASECLASS, CLASSNAME, CMD_MACRO) \
|
||||
class CLASSNAME : public BASECLASS { \
|
||||
NON_COPYABLE(CLASSNAME); \
|
||||
NON_MOVEABLE(CLASSNAME); \
|
||||
private: \
|
||||
struct CommandPointerTable { \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DECLARE_FUNCTION_POINTER) \
|
||||
}; \
|
||||
private: \
|
||||
const CommandPointerTable * const cmd_table; \
|
||||
private: \
|
||||
CLASSNAME() = delete; \
|
||||
protected: \
|
||||
constexpr CLASSNAME(const CommandPointerTable *ct) \
|
||||
: cmd_table(ct) { /* ... */ } \
|
||||
virtual ~CLASSNAME() { /* ... */ } \
|
||||
public: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DECLARE_INTERFACE_FUNCTION) \
|
||||
private: \
|
||||
template<typename S, typename T> \
|
||||
requires ((std::same_as<CLASSNAME, S> && !std::same_as<CLASSNAME, T>&& Is##CLASSNAME<T>) && \
|
||||
(::ams::sf::IsMitmServiceObject<S> == ::ams::sf::IsMitmServiceImpl<T>)) \
|
||||
struct ImplGenerator { \
|
||||
public: \
|
||||
class ImplHolder : public S { \
|
||||
private: \
|
||||
T impl; \
|
||||
public: \
|
||||
template<typename... Args> requires std::constructible_from<T, Args...> \
|
||||
constexpr ImplHolder(Args &&... args) \
|
||||
: S(std::addressof(CommandPointerTableImpl)), impl(std::forward<Args>(args)...) \
|
||||
{ \
|
||||
/* ... */ \
|
||||
} \
|
||||
ALWAYS_INLINE T &GetImpl() { return this->impl; } \
|
||||
ALWAYS_INLINE const T &GetImpl() const { return this->impl; } \
|
||||
\
|
||||
template<typename U = S> requires ::ams::sf::IsMitmServiceObject<S> && std::same_as<U, S> \
|
||||
static ALWAYS_INLINE bool ShouldMitm(os::ProcessId p, ncm::ProgramId r) { return T::ShouldMitm(p, r); } \
|
||||
private: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DECLARE_INTERFACE_FUNCTION_INVOKER_HOLDER) \
|
||||
public: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DECLARE_INTERFACE_FUNCTION_IMPL) \
|
||||
private: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_INTERFACE_IMPL_FUNCTION_POINTER_HOLDER) \
|
||||
public: \
|
||||
static constexpr CommandPointerTable CommandPointerTableImpl = { \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_INTERFACE_COMMAND_POINTER_TABLE_MEMBER) \
|
||||
}; \
|
||||
}; \
|
||||
static_assert(Is##CLASSNAME<ImplHolder>); \
|
||||
\
|
||||
class ImplPointer : public S { \
|
||||
private: \
|
||||
T *impl; \
|
||||
public: \
|
||||
constexpr ImplPointer(T *t) \
|
||||
: S(std::addressof(CommandPointerTableImpl)), impl(t) \
|
||||
{ \
|
||||
/* ... */ \
|
||||
} \
|
||||
ALWAYS_INLINE T &GetImpl() { return *this->impl; } \
|
||||
ALWAYS_INLINE const T &GetImpl() const { return *this->impl; } \
|
||||
private: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DECLARE_INTERFACE_FUNCTION_INVOKER_POINTER) \
|
||||
public: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DECLARE_INTERFACE_FUNCTION_IMPL_PTR) \
|
||||
private: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_INTERFACE_IMPL_FUNCTION_POINTER_HOLDER) \
|
||||
public: \
|
||||
static constexpr CommandPointerTable CommandPointerTableImpl = { \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_INTERFACE_COMMAND_POINTER_TABLE_MEMBER) \
|
||||
}; \
|
||||
}; \
|
||||
\
|
||||
class ImplSharedPointer : public S { \
|
||||
private: \
|
||||
std::shared_ptr<T> impl; \
|
||||
public: \
|
||||
constexpr ImplSharedPointer(std::shared_ptr<T> &&t) \
|
||||
: S(std::addressof(CommandPointerTableImpl)), impl(std::move(t)) \
|
||||
{ \
|
||||
/* ... */ \
|
||||
} \
|
||||
ALWAYS_INLINE T &GetImpl() { return *this->impl; } \
|
||||
ALWAYS_INLINE const T &GetImpl() const { return *this->impl; } \
|
||||
private: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DECLARE_INTERFACE_FUNCTION_INVOKER_SHARED_POINTER) \
|
||||
public: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DECLARE_INTERFACE_FUNCTION_IMPL_PTR) \
|
||||
private: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_INTERFACE_IMPL_FUNCTION_POINTER_HOLDER) \
|
||||
public: \
|
||||
static constexpr CommandPointerTable CommandPointerTableImpl = { \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_INTERFACE_COMMAND_POINTER_TABLE_MEMBER) \
|
||||
}; \
|
||||
}; \
|
||||
static_assert(Is##CLASSNAME<ImplHolder>); \
|
||||
}; \
|
||||
private: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_INTERFACE_SERVICE_COMMAND_META_HOLDER) \
|
||||
public: \
|
||||
template<typename T> requires (!std::same_as<CLASSNAME, T>&& Is##CLASSNAME<T>) \
|
||||
using ImplHolder = typename ImplGenerator<CLASSNAME, T>::ImplHolder; \
|
||||
\
|
||||
template<typename T> requires (!std::same_as<CLASSNAME, T>&& Is##CLASSNAME<T>) \
|
||||
using ImplPointer = typename ImplGenerator<CLASSNAME, T>::ImplPointer; \
|
||||
\
|
||||
template<typename T> requires (!std::same_as<CLASSNAME, T>&& Is##CLASSNAME<T> && \
|
||||
std::derived_from<T, std::enable_shared_from_this<T>>) \
|
||||
using ImplSharedPointer = typename ImplGenerator<CLASSNAME, T>::ImplSharedPointer; \
|
||||
\
|
||||
AMS_SF_CMIF_IMPL_DEFINE_SERVICE_DISPATCH_TABLE { \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_CMIF_SERVICE_COMMAND_META_TABLE_ENTRY) \
|
||||
}; \
|
||||
};
|
||||
|
||||
#define AMS_SF_METHOD_INFO_6(CLASSNAME, HANDLER, CMD_ID, RETURN, NAME, ARGS) \
|
||||
HANDLER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, hos::Version_Min, hos::Version_Max)
|
||||
|
||||
#define AMS_SF_METHOD_INFO_7(CLASSNAME, HANDLER, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN) \
|
||||
HANDLER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, hos::Version_Max)
|
||||
|
||||
#define AMS_SF_METHOD_INFO_8(CLASSNAME, HANDLER, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
HANDLER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX)
|
||||
|
||||
#define AMS_SF_METHOD_INFO_X(_, _0, _1, _2, _3, _4, _5, _6, _7, FUNC, ...) FUNC
|
||||
|
||||
#define AMS_SF_METHOD_INFO(...) \
|
||||
AMS_SF_METHOD_INFO_X(, ## __VA_ARGS__, AMS_SF_METHOD_INFO_8(__VA_ARGS__), AMS_SF_METHOD_INFO_7(__VA_ARGS__), AMS_SF_METHOD_INFO_6(__VA_ARGS__))
|
||||
|
||||
#define AMS_SF_DEFINE_INTERFACE(CLASSNAME, CMD_MACRO) \
|
||||
AMS_SF_IMPL_DECLARE_HELPERS(CLASSNAME,CMD_MACRO) \
|
||||
AMS_SF_IMPL_DEFINE_CONCEPT(CLASSNAME, CMD_MACRO) \
|
||||
AMS_SF_IMPL_DEFINE_CLASS( ::ams::sf::IServiceObject, CLASSNAME, CMD_MACRO) \
|
||||
static_assert(Is##CLASSNAME<CLASSNAME>);
|
||||
|
||||
#define AMS_SF_DEFINE_MITM_INTERFACE(CLASSNAME, CMD_MACRO) \
|
||||
AMS_SF_IMPL_DECLARE_HELPERS(CLASSNAME,CMD_MACRO) \
|
||||
AMS_SF_IMPL_DEFINE_CONCEPT(CLASSNAME, CMD_MACRO) \
|
||||
AMS_SF_IMPL_DEFINE_CLASS(::ams::sf::IMitmServiceObject, CLASSNAME, CMD_MACRO) \
|
||||
static_assert(Is##CLASSNAME<CLASSNAME>);
|
||||
|
||||
#define AMS_SF_IMPL_DECLARE_INTERFACE_METHODS(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, VERSION_MIN, VERSION_MAX) \
|
||||
RETURN NAME ARGS;
|
||||
|
||||
#define AMS_SF_DECLARE_INTERFACE_METHODS(CMD_MACRO) \
|
||||
CMD_MACRO(_, AMS_SF_IMPL_DECLARE_INTERFACE_METHODS)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::sf::impl {
|
||||
|
||||
template<typename Interface, typename Base, typename ImplHolder, typename ImplGetter, typename Root>
|
||||
class ImplTemplateBaseT;
|
||||
|
||||
template<typename Interface, typename Base, typename ImplHolder, typename ImplGetter>
|
||||
class ImplTemplateBase : public ImplTemplateBaseT<Interface, Base, ImplHolder, ImplGetter, Interface> {
|
||||
private:
|
||||
using BaseImpl = ImplTemplateBaseT<Interface, Base, ImplHolder, ImplGetter, Interface>;
|
||||
public:
|
||||
using BaseImpl::BaseImpl;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::sf::impl {
|
||||
|
||||
class ServiceObjectImplBase2 {
|
||||
private:
|
||||
std::atomic<u32> m_ref_count;
|
||||
protected:
|
||||
constexpr ServiceObjectImplBase2() : m_ref_count(1) { /* ... */ }
|
||||
|
||||
void AddReferenceImpl() {
|
||||
const auto prev = m_ref_count.fetch_add(1);
|
||||
AMS_ABORT_UNLESS(prev < std::numeric_limits<u32>::max());
|
||||
}
|
||||
|
||||
bool ReleaseImpl() {
|
||||
const auto prev = m_ref_count.fetch_sub(1);
|
||||
AMS_ABORT_UNLESS(prev != 0);
|
||||
return prev == 1;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user