1 #include "MapperRegistry.h"
2 #include "Mapper.h"
3 
4 #include <array>
5 #include <map>
6 #include <set>
7 #include <utility>
8 
9 namespace reanimated {
10 
startMapper(std::shared_ptr<Mapper> mapper)11 void MapperRegistry::startMapper(std::shared_ptr<Mapper> mapper) {
12   mappers[mapper->id] = mapper;
13   updatedSinceLastExecute = true;
14 }
15 
stopMapper(unsigned long id)16 void MapperRegistry::stopMapper(unsigned long id) {
17   mappers.erase(id);
18   updatedSinceLastExecute = true;
19 }
20 
execute(jsi::Runtime & rt)21 void MapperRegistry::execute(jsi::Runtime &rt) {
22   if (updatedSinceLastExecute) {
23     updateOrder();
24     updatedSinceLastExecute = false;
25   }
26   for (auto &mapper : sortedMappers) {
27     if (mapper->dirty) {
28       mapper->execute(rt);
29     }
30   }
31 }
32 
needRunOnRender()33 bool MapperRegistry::needRunOnRender() {
34   return updatedSinceLastExecute; // TODO: also run if input nodes are dirty
35 }
36 
updateOrder()37 void MapperRegistry::updateOrder() { // Topological sorting
38   sortedMappers.clear();
39 
40   struct NodeID {
41     std::shared_ptr<Mapper> mapper;
42     std::shared_ptr<MutableValue> mutableValue;
43 
44     explicit NodeID(std::shared_ptr<Mapper> mapper) {
45       if (mapper == nullptr) {
46         throw std::runtime_error(
47             "Graph couldn't be sorted (Mapper cannot be nullptr)");
48       }
49       this->mapper = mapper;
50     }
51 
52     explicit NodeID(std::shared_ptr<MutableValue> mutableValue) {
53       if (mutableValue == nullptr) {
54         throw std::runtime_error(
55             "Graph couldn't be sorted (Mutable cannot be nullptr)");
56       }
57       this->mutableValue = mutableValue;
58     }
59 
60     bool isMutable() const {
61       return mutableValue != nullptr;
62     }
63 
64     bool operator<(const NodeID &other) const {
65       if (isMutable() != other.isMutable())
66         return isMutable() < other.isMutable();
67 
68       if (isMutable()) {
69         return mutableValue < other.mutableValue;
70       }
71 
72       return mapper < other.mapper;
73     }
74   };
75 
76   std::map<NodeID, int> deg;
77 
78   std::map<std::shared_ptr<MutableValue>, std::vector<std::shared_ptr<Mapper>>>
79       mappersThatUseSharedValue;
80 
81   std::set<std::pair<int, NodeID>> nodes;
82 
83   std::function<void(NodeID)> update = [&](NodeID id) {
84     auto entry = std::make_pair(deg[id], id);
85     if (nodes.find(entry) == nodes.end())
86       return;
87     nodes.erase(entry);
88     entry.first--;
89     deg[id]--;
90     nodes.insert(entry);
91   };
92 
93   for (auto &entry : mappers) {
94     auto id = NodeID(entry.second);
95     auto &mapper = entry.second;
96     deg[id] = mapper->inputs.size();
97     nodes.insert(std::make_pair(deg[id], id));
98 
99     for (auto sharedValue : mapper->inputs) {
100       auto sharedValueID = NodeID(sharedValue);
101       mappersThatUseSharedValue[sharedValue].push_back(mapper);
102       if (deg.count(sharedValueID) == 0) {
103         deg[sharedValueID] = 0;
104       }
105     }
106 
107     for (auto sharedValue : mapper->outputs) {
108       deg[NodeID(sharedValue)]++;
109     }
110   }
111 
112   for (auto &entry : deg) {
113     auto id = entry.first;
114     if (id.isMutable()) {
115       nodes.insert(std::make_pair(entry.second, id));
116     }
117   }
118 
119   while (nodes.size() > 0 && nodes.begin()->first == 0) {
120     auto entry = *nodes.begin();
121     nodes.erase(entry);
122 
123     auto id = entry.second;
124     std::vector<NodeID> toUpdate;
125 
126     if (id.isMutable()) {
127       for (auto id : mappersThatUseSharedValue[id.mutableValue]) {
128         toUpdate.push_back(NodeID(id));
129       }
130     } else {
131       for (auto sharedValue : id.mapper->outputs) {
132         toUpdate.push_back(NodeID(sharedValue));
133       }
134 
135       sortedMappers.push_back(id.mapper);
136     }
137 
138     for (auto &id : toUpdate)
139       update(id);
140   }
141 
142   if (nodes.size() > 0) {
143     throw std::runtime_error("Cycle in mappers graph!");
144   }
145 }
146 
147 } // namespace reanimated
148