// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/blob/master/LICENSE.md #pragma once #include #include #include namespace app { class ApplicationCommon; // Forward declaration using RequestId = std::uint64_t; class AsyncCallbackReceiver; enum class ReceiverBehavior { None, WaitForResponseToClose }; class AsyncCallbacksDeleter { public: virtual ~AsyncCallbacksDeleter() noexcept = default; virtual void cancelCallbacks(AsyncCallbackReceiver *receiver) = 0; }; class AsyncCallbackReceiver { public: using Ptr = AsyncCallbackReceiver *; explicit AsyncCallbackReceiver(AsyncCallbacksDeleter *deleter) noexcept; virtual ~AsyncCallbackReceiver() = 0; private: AsyncCallbacksDeleter *deleter; }; using CallbackFunction = std::function; /** * Executes an operation on the sender's thread and saves the info about the receiver context for callback use. * Intended to use in order to avoid callbacks called on invalid receiver contexts. */ class AsyncTask { public: virtual ~AsyncTask() noexcept = default; /** * Executes a task in application's thread and saves the receiver object. * @param application Application * @param receiverObject The context of receiver */ void execute(ApplicationCommon *application, AsyncCallbackReceiver::Ptr receiverObject, std::optional> callback = std::nullopt, ReceiverBehavior receiverBehavior = ReceiverBehavior::None); private: /** * The specific operation that is to be executed by a task. * @param application Application * @return Request identifier, to be matched with a response. */ [[nodiscard]] virtual auto onExecute(ApplicationCommon *application) -> RequestId = 0; }; /** * A database query that is using the mechanism of AsyncTask. */ class AsyncQuery : public AsyncTask { public: [[nodiscard]] static auto createFromQuery(std::unique_ptr &&query, db::Interface::Name target) -> std::unique_ptr; AsyncQuery(std::unique_ptr &&query, db::Interface::Name target) noexcept; void setCallback(db::QueryCallbackFunction &&callback) noexcept; void setCallback(std::unique_ptr &&listener) noexcept; private: [[nodiscard]] auto onExecute(ApplicationCommon *application) -> RequestId override; std::unique_ptr query; db::Interface::Name target; }; class AsyncRequest : public AsyncTask { public: [[nodiscard]] static auto createFromMessage(std::unique_ptr &&message, std::string serviceName) -> std::unique_ptr; AsyncRequest(std::unique_ptr &&message, std::string serviceName) noexcept; private: [[nodiscard]] auto onExecute(ApplicationCommon *application) -> RequestId override; std::unique_ptr message; std::string serviceName; }; class AsyncCallback { public: virtual ~AsyncCallback() noexcept = default; [[nodiscard]] virtual auto execute() -> bool = 0; }; class NullCallback : public AsyncCallback { public: [[nodiscard]] auto execute() -> bool override; }; class QueryCallback : public AsyncCallback { public: explicit QueryCallback(db::QueryResponse *response); [[nodiscard]] auto execute() -> bool override; private: db::QueryResponse *response = nullptr; }; class AsyncResponseCallback : public AsyncCallback { public: AsyncResponseCallback(sys::ResponseMessage *response, CallbackFunction callbackFunction); [[nodiscard]] auto execute() -> bool override; private: sys::ResponseMessage *response = nullptr; CallbackFunction callbackFunction; }; } // namespace app