esphome-ratgdo/components/ratgdo/observable.h

82 lines
1.8 KiB
C
Raw Normal View History

#pragma once
#include <functional>
#include <utility>
#include <vector>
namespace esphome {
namespace ratgdo {
template <typename T>
2024-01-16 23:22:57 +00:00
class distinct_observable;
template <typename T>
class observable_base {
public:
2024-01-16 23:22:57 +00:00
template <typename Observer>
void subscribe(Observer&& observer)
{
2024-01-16 23:22:57 +00:00
this->observers_.push_back(std::forward<Observer>(observer));
}
2024-01-16 23:22:57 +00:00
void notify(T value) const
{
for (const auto& observer : this->observers_) {
observer(value);
}
}
distinct_observable<T> distinct()
{
return std::make_shared(this);
}
private:
std::vector<std::function<void(T)>> observers_;
};
template <typename T>
class observable : public observable_base<T> {
public:
observable(const T& value) : value_(value) {}
template <typename U>
observable& operator=(U value)
{
if (value != this->value_) {
this->value_ = value;
2024-01-16 23:22:57 +00:00
this->notify(value);
}
return *this;
}
T const* operator&() const { return &this->value_; }
T const& operator*() const { return this->value_; }
2024-01-16 23:22:57 +00:00
private:
T value_;
};
2024-01-16 23:22:57 +00:00
template <typename T>
class distinct_observable : public observable<T> {
public:
distinct_observable(std::shared_ptr<observable<T>> inner) : inner_(inner) {
inner.subscribe([=] (T value) {
if (value != this->value_) {
this->value_ = value;
this->notify(value);
}
});
}
private:
2024-01-16 23:22:57 +00:00
std::shared_ptr<observable<T>> inner_;
T value_;
};
} // namespace ratgdo
} // namespace esphome