FCT
载入中...
搜索中...
未找到
ObjectPipe.h
浏览该文件的文档.
1//
2// Created by Administrator on 2025/8/21.
3//
4
5#ifndef OBJECTPIPE_H
6#define OBJECTPIPE_H
7#include "../ThirdParty.h"
8#include <unordered_map>
9#include <vector>
10#include <functional>
11#include <memory>
12namespace FCT {
13 using SubscribeId = std::size_t;
15 virtual ~IObjectDispatcher() = default;
16 virtual void unsubscribe(SubscribeId id) = 0;
17 };
18 template<typename Token,typename Object>
20 size_t index = 0;
21 boost::unordered_flat_map<SubscribeId, std::function<void(Object&)>> get;
22 boost::unordered_flat_map<SubscribeId, std::function<void()>> lost;
23 Object* object = nullptr;
24 std::unique_ptr<Object> ownedObject = nullptr;
25 Token token;
26 ObjectDispatcher(const Token& t) : token(t) {}
27 SubscribeId subscribeGet(std::function<void(Object&)> getFunc) {
28 std::size_t seed = 0;
29 boost::hash_combine(seed, index++);
30 boost::hash_combine(seed, entt::type_hash<Object>::value());
31 boost::hash_combine(seed, std::hash<Token>{}(token));
32 get[seed] = getFunc;
33
34 if (object) {
35 getFunc(*object);
36 }
37
38 return seed;
39 }
40 SubscribeId subscribeLost(std::function<void()> lostFunc) {
41 std::size_t seed = 0;
42 boost::hash_combine(seed, index++);
43 boost::hash_combine(seed, entt::type_hash<Object>::value());
44 boost::hash_combine(seed, std::hash<Token>{}(token));
45 lost[seed] = lostFunc;
46 return seed;
47 }
48
49 void unsubscribe(SubscribeId id) override
50 {
51 if (get.contains(id)) {
52 get.erase(id);
53 }
54 if (lost.contains(id)) {
55 lost.erase(id);
56 }
57 }
58
59 void push(Object* obj) {
60 ownedObject.reset();
61 object = obj;
62 for (const auto& [id, callback] : get) {
63 callback(*obj);
64 }
65 }
66 void pushOwned(Object&& obj) {
67 ownedObject = std::make_unique<Object>(std::move(obj));
68 object = ownedObject.get();
69 for (const auto& [id, callback] : get) {
70 callback(*object);
71 }
72 }
73
74 void pop() {
75 for (const auto& [id, callback] : lost) {
76 callback();
77 }
78 object = nullptr;
79 ownedObject.reset();
80 }
81 void trigger(Object* obj) {
82 for (const auto& [id, callback] : get) {
83 callback(*obj);
84 }
85 for (const auto& [id, callback] : lost) {
86 callback();
87 }
88 }
89 };
90 template<typename Token>
91 class PipePort;
92 template<typename Token>
93 class ObjectPipe {
94 private:
95 std::unordered_map<Token, std::unordered_map<std::size_t, std::unique_ptr<IObjectDispatcher>>> m_tokenDispatchers;
96 template<typename Object>
98 auto typeHash = entt::type_hash<Object>::value();
99
100 if (m_tokenDispatchers[token].find(typeHash) == m_tokenDispatchers[token].end()) {
101 m_tokenDispatchers[token][typeHash] = std::make_unique<ObjectDispatcher<Token, Object>>(token);
102 }
103
104 return static_cast<ObjectDispatcher<Token, Object>*>(m_tokenDispatchers[token][typeHash].get());
105 }
106 public:
107 template<typename Object, typename FuncGet>
108 SubscribeId subscribe(const Token& token, FuncGet&& getFunc) {
109 auto dispatcher = getOrCreateDispatcher<Object>(token);
110 return dispatcher->subscribeGet([getFunc](Object& obj) {
111 getFunc(obj);
112 });
113 }
114 template<typename Object, typename FuncGet, typename FuncLost>
115 std::pair<SubscribeId, SubscribeId> subscribe(const Token& token,
116 FuncGet&& getFunc,
117 FuncLost&& lostFunc) {
118 auto dispatcher = getOrCreateDispatcher<Object>(token);
119 auto getId = dispatcher->subscribeGet([getFunc = std::forward<FuncGet>(getFunc)](Object& obj) {
120 getFunc(obj);
121 });
122 auto lostId = dispatcher->subscribeLost([lostFunc = std::forward<FuncLost>(lostFunc)]() {
123 lostFunc();
124 });
125 return {getId, lostId};
126 }
127 template<typename Object>
128 void provide(const Token& token, Object& object) {
129 auto dispatcher = getOrCreateDispatcher<std::decay_t<Object>>(token);
130 dispatcher->push(&object);
131 }
132
133 template<typename Object>
134 void provide(const Token& token, Object&& object) {
135 auto dispatcher = getOrCreateDispatcher<std::decay_t<Object>>(token);
136 dispatcher->pushOwned(std::forward<Object>(object));
137 }
138 template<typename Object>
139 void remove(const Token& token) {
140 auto dispatcher = getOrCreateDispatcher<Object>(token);
141 dispatcher->pop();
142 }
143 template<typename Object>
144 void trigger(const Token& token, Object* object) {
145 auto dispatcher = getOrCreateDispatcher<Object>(token);
146 dispatcher->trigger(object);
147 }
148 void unsubscribe(const Token& token, SubscribeId id) {
149 if (auto tokenIt = m_tokenDispatchers.find(token); tokenIt != m_tokenDispatchers.end()) {
150 for (auto& [typeHash, dispatcher] : tokenIt->second) {
151 dispatcher->unsubscribe(id);
152 }
153 }
154 }
155 PipePort<Token> getPort(const Token& token);
156 };
157} // FCT
158
159#endif //OBJECTPIPE_H
void unsubscribe(const Token &token, SubscribeId id)
std::pair< SubscribeId, SubscribeId > subscribe(const Token &token, FuncGet &&getFunc, FuncLost &&lostFunc)
PipePort< Token > getPort(const Token &token)
void provide(const Token &token, Object &object)
ObjectDispatcher< Token, Object > * getOrCreateDispatcher(const Token &token)
void trigger(const Token &token, Object *object)
void remove(const Token &token)
std::unordered_map< Token, std::unordered_map< std::size_t, std::unique_ptr< IObjectDispatcher > > > m_tokenDispatchers
void provide(const Token &token, Object &&object)
SubscribeId subscribe(const Token &token, FuncGet &&getFunc)
std::size_t SubscribeId
virtual ~IObjectDispatcher()=default
virtual void unsubscribe(SubscribeId id)=0
void push(Object *obj)
void trigger(Object *obj)
SubscribeId subscribeGet(std::function< void(Object &)> getFunc)
ObjectDispatcher(const Token &t)
SubscribeId subscribeLost(std::function< void()> lostFunc)
boost::unordered_flat_map< SubscribeId, std::function< void()> > lost
void unsubscribe(SubscribeId id) override
std::unique_ptr< Object > ownedObject
boost::unordered_flat_map< SubscribeId, std::function< void(Object &)> > get
void pushOwned(Object &&obj)