1616#include < type_traits>
1717#include < utility>
1818#include < vector>
19+ #include < map>
20+ #include < mutex>
1921
2022#include < tbb/concurrent_queue.h>
2123#include < tbb/task.h>
@@ -30,27 +32,49 @@ template <typename K>
3032class PtrCache
3133{
3234public:
33- void Add (const K& key, const std::shared_ptr<void >& ptr)
35+ template <typename V, typename F>
36+ std::shared_ptr<V> LookupOrCreate (const K& key, F&& createFunc)
3437 {
35- auto res = map1_.insert (key, ptr);
36- if (res.first == true )
38+ std::lock_guard<std::mutex> scopedLock (mutex_);
39+
40+ auto it = map1_.find (key);
41+
42+ if (it != map1_.end ())
3743 {
38- map2_.insert (ptr , res.second );
39- return true ;
44+ if (auto ptr = it->second .lock ())
45+ {
46+ return std::static_pointer_cast<V>(ptr);
47+ }
4048 }
41-
49+
50+ std::shared_ptr<V> v = createFunc ();
51+ auto res = map1_.insert ({ key, std::weak_ptr<void >{ v } });
52+ map2_[v.get ()] = res.first ;
53+ return v;
4254 }
4355
44- void Remove (const std::shared_ptr<void >& ptr)
56+ template <typename V>
57+ void Erase (const std::shared_ptr<V>& ptr)
4558 {
46- map2_.remove ();
59+ std::lock_guard<std::mutex> scopedLock (mutex_);
60+
61+ auto it = map2_.find ((void *)ptr.get ());
62+
63+ if (it != map2_.end ())
64+ {
65+ map1_.erase (it->second );
66+ map2_.erase (it);
67+ }
4768 }
4869
4970private:
50- std::mutex lock_;
71+ std::mutex mutex_;
72+
73+ using Map1Type = std::map<K, std::weak_ptr<void >>;
74+ using Map2Type = std::unordered_map<void *, typename Map1Type::iterator>;
5175
52- std::map<K, std::weak_ptr< void >> map1_;
53- std::unordered_map< void *, std::map::iterator> map2_;
76+ Map1Type map1_;
77+ Map2Type map2_;
5478};
5579
5680class ReactiveGraph ;
@@ -115,6 +139,8 @@ class TransactionQueue
115139class ReactiveGraph
116140{
117141public:
142+ using LinkCacheType = PtrCache<std::pair<void *, void *>>;
143+
118144 NodeId RegisterNode (IReactiveNode* nodePtr, NodeCategory category);
119145 void UnregisterNode (NodeId nodeId);
120146
@@ -129,6 +155,9 @@ class ReactiveGraph
129155
130156 template <typename F>
131157 void EnqueueTransaction (TransactionFlags flags, F&& transactionCallback);
158+
159+ LinkCacheType& GetLinkCache ()
160+ { return linkCache_; }
132161
133162private:
134163 struct NodeData
@@ -189,7 +218,9 @@ class ReactiveGraph
189218 TopoQueue scheduledNodes_;
190219 IndexMap<NodeData> nodeData_;
191220 std::vector<NodeId> changedInputs_;
192- LinkOutputMap scheduledLinkOutputs_;
221+ LinkOutputMap scheduledLinkOutputs_;
222+
223+ LinkCacheType linkCache_;
193224
194225 bool isTransactionActive_ = false ;
195226};
@@ -202,7 +233,6 @@ NodeId ReactiveGraph::RegisterNode(IReactiveNode* nodePtr, NodeCategory category
202233void ReactiveGraph::UnregisterNode (NodeId nodeId)
203234{
204235 nodeData_.Remove (nodeId);
205-
206236}
207237
208238void ReactiveGraph::OnNodeAttach (NodeId nodeId, NodeId parentId)
@@ -224,16 +254,6 @@ void ReactiveGraph::OnNodeDetach(NodeId nodeId, NodeId parentId)
224254 successors.erase (std::find (successors.begin (), successors.end (), nodeId));
225255}
226256
227- void ReactiveGraph::OnDynamicNodeAttach (NodeId nodeId, NodeId parentId, TurnId turnId)
228- {
229- OnNodeAttach (nodeId, parentId);
230- }
231-
232- void ReactiveGraph::OnDynamicNodeDetach (NodeId nodeId, NodeId parentId, TurnId turnId)
233- {
234- OnNodeDetach (nodeId, parentId);
235- }
236-
237257template <typename F>
238258void ReactiveGraph::AddInput (NodeId nodeId, F&& inputCallback)
239259{
0 commit comments