enum class WeatherKind { kSunny, kRainy };
class WeatherStorage final {
public:
explicit WeatherStorage(WeatherKind value)
: value_(value), channel_("weather") {}
WeatherKind Get() const { return value_.load(); }
template <typename Class>
Class* obj, std::string_view name, void (Class::*func)(WeatherKind)) {
return channel_.DoUpdateAndListen(obj, name, func,
[&] { (obj->*func)(Get()); });
}
void Set(WeatherKind value) {
value_.store(value);
channel_.SendEvent(value);
}
private:
std::atomic<WeatherKind> value_;
};
enum class CoatKind { kJacket, kRaincoat };
class CoatStorage final {
public:
explicit CoatStorage(WeatherStorage& weather_storage) {
weather_subscriber_ = weather_storage.UpdateAndListen(
this, "coats", &CoatStorage::OnWeatherUpdate);
}
~CoatStorage() { weather_subscriber_.Unsubscribe(); }
CoatKind Get() const { return value_.load(); }
private:
void OnWeatherUpdate(WeatherKind weather) {
value_.store(ComputeCoat(weather));
}
static CoatKind ComputeCoat(WeatherKind weather);
std::atomic<CoatKind> value_{};
};
UTEST(AsyncEventChannel, UpdateAndListenSample) {
WeatherStorage weather_storage(WeatherKind::kSunny);
CoatStorage coat_storage(weather_storage);
EXPECT_EQ(coat_storage.Get(), CoatKind::kJacket);
weather_storage.Set(WeatherKind::kRainy);
EXPECT_EQ(coat_storage.Get(), CoatKind::kRaincoat);
}