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