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