#include "fiko/cekirdek/recompute.hpp" #include #include #include #include "fiko/cekirdek/cekirdek.hpp" #include "fiko/cekirdek/olay.hpp" namespace fiko { namespace { // Nesne deposundan OutList haritasi kur: varlik -> bagimliliklar (girdiler). // Yalniz gecerli (yasayan, nesnesi olan) varliklar dahil edilir. std::unordered_map> outListKur(Cekirdek& c) { std::unordered_map> out; Depo& depo = c.nesneler(); out.reserve(depo.boyut()); for (auto [v, kok] : depo) { if (!kok) continue; out.emplace(v, kok->bagimliliklar()); } return out; } } // namespace void RecomputeMotor::kirlet(Cekirdek& c, Varlik v) { kirli_.insert(v); // Ters kenar (InList): girdi -> ona bagimli olanlar. OutList'ten cevir. const auto out = outListKur(c); std::unordered_map> in; in.reserve(out.size()); for (const auto& [dugum, girdiler] : out) for (Varlik g : girdiler) in[g].push_back(dugum); // v'den InList boyunca BFS: v'ye (dolayli) bagimli her nesneyi kirlet. std::vector yigin{v}; while (!yigin.empty()) { const Varlik u = yigin.back(); yigin.pop_back(); auto it = in.find(u); if (it == in.end()) continue; for (Varlik bagimli : it->second) if (kirli_.insert(bagimli).second) yigin.push_back(bagimli); } } void RecomputeMotor::hesapla(Cekirdek& c, OlayGunlugu& olaylar) { if (kirli_.empty()) return; const auto out = outListKur(c); // Kirli kumenin topolojik sirasi: girdi (bagimlilik) once hesaplanir. // DFS renkleri: 0 beyaz, 1 gri (yigitta), 2 siyah (bitti). std::unordered_map renk; std::vector sira; // ters-son sirali (bitis sirasi = topolojik) sira.reserve(kirli_.size()); // Ozyinelemesiz DFS: her kirli nesneden basla, girdilerine in. // NOT: renk haritasina eleman eklemek referanslari gecersizler; bu yuzden // renk degerleri kopyayla okunur/yazilir (asili referans tutulmaz). for (Varlik baslangic : kirli_) { if (renk[baslangic] != 0) continue; std::vector yigin{baslangic}; while (!yigin.empty()) { const Varlik u = yigin.back(); const int r = renk[u]; if (r == 0) { renk[u] = 1; // gri: girdilerini isle auto it = out.find(u); if (it != out.end()) { for (Varlik g : it->second) { // Yalniz kirli kume icindeki girdiler siralanir; digerleri // zaten guncel kabul edilir. if (kirli_.find(g) == kirli_.end()) continue; const int rg = renk[g]; // yoksa 0 (beyaz) ekler if (rg == 1) { // Gri'ye donus = cevrim. O kenar kirilir + uyari. std::fprintf(stderr, "[recompute] cevrim tespit edildi: varlik %u atlaniyor\n", static_cast(g)); continue; } if (rg == 0) yigin.push_back(g); } } } else { if (r == 1) { renk[u] = 2; // siyah: girdileri bitti, sirala sira.push_back(u); } yigin.pop_back(); } } } // sira zaten topolojik (girdi once). Hesapla. Depo& depo = c.nesneler(); u32 sayilan = 0; for (Varlik v : sira) { NesneKok* kok = depo.bul(v); if (!kok || !*kok) continue; (*kok)->hesapla(c.dunya(), olaylar); ++sayilan; } kirli_.clear(); olaylar.yayinla(HesaplamaBitti{sayilan}); } } // namespace fiko