|
|
#pragma once
|
|
|
|
|
|
#include <cstdint>
|
|
|
#include <memory>
|
|
|
#include <string>
|
|
|
#include <type_traits>
|
|
|
#include <unordered_map>
|
|
|
|
|
|
#include <rpc/RpcValue.h>
|
|
|
|
|
|
// Базовый интерфейс для всех RPC-объектов, живущих в реестре.
|
|
|
// Каждая реализация (обычно *Skeleton) знает, как вызвать реальные методы.
|
|
|
struct IRpcObject {
|
|
|
virtual ~IRpcObject() = default;
|
|
|
|
|
|
virtual RpcValue invoke(const std::string& method,
|
|
|
const RpcArgs& args) = 0;
|
|
|
};
|
|
|
|
|
|
// Специализированный реестр объектов именно для RPC-уровня.
|
|
|
// Владеет скелетонами (IRpcObject) через unique_ptr. Сами доменные объекты
|
|
|
// (MyService и т.п.) живут снаружи и могут быть обёрнуты в shared_ptr.
|
|
|
class RpcRegistry {
|
|
|
public:
|
|
|
// PoC: ObjectId храним как int-совместимый тип, чтобы его можно было
|
|
|
// передавать через BaseIpcMessage, который поддерживает только int/string.
|
|
|
using ObjectId = int;
|
|
|
|
|
|
RpcRegistry() = default;
|
|
|
|
|
|
// Зарегистрировать объект-обёртку (обычно Skeleton) и вернуть его
|
|
|
// идентификатор. По сути, это registerSkeleton<T>(...).
|
|
|
template<typename T, typename... Args>
|
|
|
ObjectId registerObject(Args&&... args) {
|
|
|
static_assert(std::is_base_of_v<IRpcObject, T>,
|
|
|
"T must inherit IRpcObject");
|
|
|
|
|
|
const ObjectId id = nextId_++;
|
|
|
objects_.emplace(
|
|
|
id, std::make_unique<T>(std::forward<Args>(args)...));
|
|
|
return id;
|
|
|
}
|
|
|
|
|
|
// Уничтожить объект по идентификатору.
|
|
|
void destroyObject(ObjectId id) {
|
|
|
objects_.erase(id);
|
|
|
}
|
|
|
|
|
|
// Найти объект по идентификатору.
|
|
|
IRpcObject* get(ObjectId id) const {
|
|
|
auto it = objects_.find(id);
|
|
|
return it == objects_.end() ? nullptr : it->second.get();
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
std::unordered_map<ObjectId, std::unique_ptr<IRpcObject>> objects_;
|
|
|
ObjectId nextId_ = 0; // первый объект будет иметь id = 0 (PoC)
|
|
|
};
|
|
|
|
|
|
|
|
|
|