|  | // 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_ |