diff options
author | Roman Smrž <roman.smrz@seznam.cz> | 2021-04-18 22:25:17 +0200 |
---|---|---|
committer | Roman Smrž <roman.smrz@seznam.cz> | 2021-04-18 22:28:59 +0200 |
commit | 9aaba1211c95dc7e08437a7cca73452181e296d6 (patch) | |
tree | b11cb72c1515fb7b284e98708d6b6f4a8fbae3ab /src/frp.cpp | |
parent | c3d6046b25ef0786b8d2919dfa9db4eb05114501 (diff) |
Initial support for FRP behaviors
Diffstat (limited to 'src/frp.cpp')
-rw-r--r-- | src/frp.cpp | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/frp.cpp b/src/frp.cpp new file mode 100644 index 0000000..142fcd4 --- /dev/null +++ b/src/frp.cpp @@ -0,0 +1,133 @@ +#include <erebos/frp.h> + +#include <condition_variable> +#include <mutex> + +using namespace erebos; + +using std::condition_variable; +using std::move; +using std::mutex; +using std::nullopt; +using std::unique_lock; +using std::weak_ptr; + +mutex bhvTimeMutex; +condition_variable bhvTimeCond; +bool bhvTimeRunning = false; +uint64_t bhvTimeLast = 0; + +BhvCurTime::BhvCurTime() +{ + unique_lock lock(bhvTimeMutex); + bhvTimeCond.wait(lock, []{ return !bhvTimeRunning; }); + + bhvTimeRunning = true; + t = BhvTime(++bhvTimeLast); +} + +BhvCurTime::~BhvCurTime() +{ + if (t) { + unique_lock lock(bhvTimeMutex); + bhvTimeRunning = false; + lock.unlock(); + bhvTimeCond.notify_one(); + } +} + +BhvCurTime::BhvCurTime(BhvCurTime && other) +{ + t = other.t; + other.t = nullopt; +} + +BhvCurTime & BhvCurTime::operator=(BhvCurTime && other) +{ + t = other.t; + other.t = nullopt; + return *this; +} + + +BhvImplBase::~BhvImplBase() = default; + +void BhvImplBase::dependsOn(shared_ptr<BhvImplBase> other) +{ + depends.push_back(other); + other->rdepends.push_back(shared_from_this()); +} + +void BhvImplBase::updated(const BhvCurTime & ctime) +{ + vector<shared_ptr<BhvImplBase>> toUpdate; + markDirty(ctime, toUpdate); + + for (auto & bhv : toUpdate) + bhv->updateDirty(ctime); +} + +void BhvImplBase::markDirty(const BhvCurTime & ctime, vector<shared_ptr<BhvImplBase>> & toUpdate) +{ + if (dirty) + return; + + if (!needsUpdate(ctime)) + return; + + dirty = true; + toUpdate.push_back(shared_from_this()); + + bool prune = false; + for (const auto & w : rdepends) { + if (auto b = w.lock()) + b->markDirty(ctime, toUpdate); + else + prune = true; + } + + if (prune) { + decltype(rdepends) pruned; + for (const auto & w : rdepends) + if (!w.expired()) + pruned.push_back(move(w)); + rdepends = move(pruned); + } +} + +void BhvImplBase::updateDirty(const BhvCurTime & ctime) +{ + if (!dirty) + return; + + for (auto & d : depends) + d->updateDirty(ctime); + + doUpdate(ctime); + dirty = false; + + bool prune = false; + for (const auto & wcb : watchers) { + if (auto cb = wcb.lock()) + (*cb)(ctime); + else + prune = true; + } + + if (prune) { + decltype(watchers) pruned; + for (const auto & w : watchers) + if (!w.expired()) + pruned.push_back(move(w)); + watchers = move(pruned); + } +} + +bool BhvImplBase::needsUpdate(const BhvCurTime &) const +{ + return true; +} + +void BhvImplBase::doUpdate(const BhvCurTime &) +{ +} |