blob: 23993ea1a14c35759bb6cf73665fb6c79b77c7ea [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_UI_SCENIC_LIB_FLATLAND_HANGING_GET_HELPER_H_
#define SRC_UI_SCENIC_LIB_FLATLAND_HANGING_GET_HELPER_H_
#include <fuchsia/ui/scenic/internal/cpp/fidl.h>
#include <lib/fit/function.h>
namespace flatland {
/// A helper class for managing [hanging get
/// semantics](https://fuchsia.dev/fuchsia-src/development/api/fidl.md#delay-responses-using-hanging-gets).
/// It responds with the most recently updated value.
///
/// For each hanging get method in a FIDL interface, like GetData() -> ( Data response ), create one
/// of these classes. Any time the response should change, call Update(Data x). Any time the client
/// calls GetFoo(), set the callback on this helper. Once the callback has been set and the data has
/// been updated, the callback will be triggered with the new data.
///
/// Each callback will only be triggered once. Each Update will only trigger, at most, a single
/// callback. Update(Data x) is idempotent. Calling it with the same value will not trigger a new
/// execution of a registered callback, nor will it remove the registered callback.
///
/// The templated Data parameter must be a FIDL type, one that supports both fidl::Clone and
/// fidl::Equals.
template <class Data>
class HangingGetHelper {
public:
using Callback = fit::function<void(Data)>;
HangingGetHelper() = default;
void Update(Data data) {
if (last_data_ && fidl::Equals(last_data_.value(), data)) {
return;
}
data_ = std::move(data);
SendIfReady();
}
void SetCallback(Callback callback) {
callback_ = std::move(callback);
SendIfReady();
}
private:
void SendIfReady() {
if (data_ && callback_) {
last_data_ = Data();
fidl::Clone(data_.value(), &last_data_.value());
callback_(std::move(data_.value()));
data_.reset();
callback_ = nullptr;
}
}
std::optional<Data> data_;
std::optional<Data> last_data_;
Callback callback_;
};
} // namespace flatland
#endif // SRC_UI_SCENIC_LIB_FLATLAND_HANGING_GET_HELPER_H_