~aleteoryx/muditaos

muditaos/module-apps/apps-common/AsyncTask.hpp -rw-r--r-- 4.4 KiB
a405cad6Aleteoryx trim readme 6 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// 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 <service-db/DBServiceAPI.hpp>
#include <service-db/QueryMessage.hpp>

#include <cstdint>

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<bool(sys::ResponseMessage *)>;

    /**
     * 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<std::function<bool(sys::ResponseMessage *)>> 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<db::Query> &&query, db::Interface::Name target)
            -> std::unique_ptr<AsyncQuery>;

        AsyncQuery(std::unique_ptr<db::Query> &&query, db::Interface::Name target) noexcept;

        void setCallback(db::QueryCallbackFunction &&callback) noexcept;
        void setCallback(std::unique_ptr<db::QueryListener> &&listener) noexcept;

      private:
        [[nodiscard]] auto onExecute(ApplicationCommon *application) -> RequestId override;

        std::unique_ptr<db::Query> query;
        db::Interface::Name target;
    };

    class AsyncRequest : public AsyncTask
    {
      public:
        [[nodiscard]] static auto createFromMessage(std::unique_ptr<sys::DataMessage> &&message,
                                                    std::string serviceName) -> std::unique_ptr<AsyncRequest>;

        AsyncRequest(std::unique_ptr<sys::DataMessage> &&message, std::string serviceName) noexcept;

      private:
        [[nodiscard]] auto onExecute(ApplicationCommon *application) -> RequestId override;

        std::unique_ptr<sys::DataMessage> 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