skyline/app/src/main/cpp/skyline/services/base_service.h
PixelyIon eff5711c49 Split monolithic common.h into smaller chunks
* Resolves dependency cycles in some components
* Allows for easier navigation of certain components like `span` which were especially large
* Some imports have been moved from `common.h` into their own files due to their infrequency
2021-10-26 10:46:36 +05:30

90 lines
4.8 KiB
C++

// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include <kernel/ipc.h>
#define SERVICE_STRINGIFY(string) #string
#define SFUNC(id, Class, Function) std::pair<u32, std::pair<Result(Class::*)(type::KSession &, ipc::IpcRequest &, ipc::IpcResponse &), const char*>>{id, {&Class::Function, SERVICE_STRINGIFY(Class::Function)}}
#define SFUNC_BASE(id, Class, BaseClass, Function) std::pair<u32, std::pair<Result(Class::*)(type::KSession &, ipc::IpcRequest &, ipc::IpcResponse &), const char*>>{id, {&Class::CallBaseFunction<BaseClass, decltype(&BaseClass::Function), &BaseClass::Function>, SERVICE_STRINGIFY(Class::Function)}}
#define SERVICE_DECL_AUTO(name, value) decltype(value) name = value
#define SERVICE_DECL(...) \
private: \
template<typename BaseClass, typename BaseFunctionType, BaseFunctionType BaseFunction> \
Result CallBaseFunction(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { \
return (static_cast<BaseClass *>(this)->*BaseFunction)(session, request, response); \
} \
SERVICE_DECL_AUTO(functions, frozen::make_unordered_map({__VA_ARGS__})); \
protected: \
ServiceFunctionDescriptor GetServiceFunction(u32 id) override { \
auto& function{functions.at(id)}; \
return ServiceFunctionDescriptor{ \
reinterpret_cast<DerivedService*>(this), \
reinterpret_cast<decltype(ServiceFunctionDescriptor::function)>(function.first), \
function.second \
}; \
}
#define SRVREG(class, ...) std::make_shared<class>(state, manager, ##__VA_ARGS__)
namespace skyline::kernel::type {
class KSession;
}
namespace skyline::service {
using namespace kernel;
using ServiceName = u64; //!< Service names are a maximum of 8 bytes so we use a u64 to store them
class ServiceManager;
/**
* @brief The base class for the HOS service interfaces hosted by sysmodules
*/
class BaseService {
private:
std::string name; //!< The name of the service, it's only assigned after GetName is called and shouldn't be used directly
protected:
const DeviceState &state;
ServiceManager &manager;
class DerivedService; //!< A placeholder derived class which is used for class function semantics
/**
* @brief A per-function descriptor for HLE service functions
*/
struct ServiceFunctionDescriptor {
DerivedService *clazz; //!< A pointer to the class that this was derived from, it's used as the 'this' pointer for the function
Result (DerivedService::*function)(type::KSession &, ipc::IpcRequest &, ipc::IpcResponse &); //!< A function pointer to a HLE implementation of the service function
const char *name; //!< A pointer to a static string in the format "Class::Function" for the specific service class/function
constexpr Result operator()(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
return (clazz->*function)(session, request, response);
}
};
public:
BaseService(const DeviceState &state, ServiceManager &manager) : state(state), manager(manager) {}
/**
* @note To be able to extract the name of the underlying class and ensure correct destruction order
*/
virtual ~BaseService() = default;
virtual ServiceFunctionDescriptor GetServiceFunction(u32 id) {
throw std::out_of_range("GetServiceFunction not implemented");
}
/**
* @return A string with the name of the service class
* @note The lifetime of the returned string is tied to that of the class
*/
const std::string &GetName();
/**
* @brief Handles an IPC Request to a service
*/
Result HandleRequest(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
};
}