~aleteoryx/muditaos

ref: 39255b2d45ffacb9de27d211c79d6a6763d69bcf muditaos/module-apps/apps-common/AsyncTask.hpp -rw-r--r-- 4.2 KiB
39255b2d — Paweł Joński [BH-743] AlarmEvent UT 4 years 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
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <service-db/DBServiceAPI.hpp>
#include <service-db/QueryMessage.hpp>

#include <cstdint>

namespace app
{
    class Application; // Forward declaration

    using RequestId = std::uint64_t;
    class AsyncCallbackReceiver;

    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(Application *application,
                     AsyncCallbackReceiver::Ptr receiverObject,
                     std::optional<std::function<bool(sys::ResponseMessage *)>> callback = std::nullopt);

      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(Application *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(Application *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;

        void setCallback(std::function<bool> &&callback) noexcept;

      private:
        [[nodiscard]] auto onExecute(Application *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