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)11void MapperRegistry::startMapper(std::shared_ptr<Mapper> mapper) { 12 mappers[mapper->id] = mapper; 13 updatedSinceLastExecute = true; 14 } 15 stopMapper(unsigned long id)16void MapperRegistry::stopMapper(unsigned long id) { 17 mappers.erase(id); 18 updatedSinceLastExecute = true; 19 } 20 execute(jsi::Runtime & rt)21void 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()33bool MapperRegistry::needRunOnRender() { 34 return updatedSinceLastExecute; // TODO: also run if input nodes are dirty 35 } 36 updateOrder()37void 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