1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H
17 #define BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H
18 
19 #include <array>
20 #include <atomic>
21 #include <list>
22 #include <map>
23 #include <mutex>
24 
25 #include "inner_event.h"
26 #include "event_handler_errors.h"
27 #include "file_descriptor_listener.h"
28 #include "dumper.h"
29 #include "logger.h"
30 
31 namespace OHOS {
32 namespace AppExecFwk {
33 class IoWaiter;
34 
35 class EventQueue final {
36 public:
37     // Priority for the events
38     enum class Priority : uint32_t {
39         // The highest priority queue, should be distributed until the tasks in the queue are completed.
40         VIP = 0,
41         // Event that should be distributed at once if possible.
42         IMMEDIATE,
43         // High priority event, sorted by handle time, should be distributed before low priority event.
44         HIGH,
45         // Normal event, sorted by handle time.
46         LOW,
47         // Event that should be distributed only if no other event right now.
48         IDLE,
49     };
50 
51     EventQueue();
52     explicit EventQueue(const std::shared_ptr<IoWaiter> &ioWaiter);
53     ~EventQueue();
54     DISALLOW_COPY_AND_MOVE(EventQueue);
55 
56     /**
57      * Insert an event into event queue with different priority.
58      * The events will be sorted by handle time.
59      *
60      * @param event Event instance which should be added into event queue.
61      * @param Priority Priority of the event
62      *
63      * @see #Priority
64      */
65     void Insert(InnerEvent::Pointer &event, Priority priority = Priority::LOW);
66 
67     /**
68      * Remove events if its owner is invalid.
69      */
70     void RemoveOrphan();
71 
72     /**
73      * Remove events with specified requirements.
74      *
75      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
76      */
77     void Remove(const std::shared_ptr<EventHandler> &owner);
78 
79     /**
80      * Remove events with specified requirements.
81      *
82      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
83      * @param innerEventId Remove events by event id.
84      */
85     void Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId);
86 
87     /**
88      * Remove events with specified requirements.
89      *
90      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
91      * @param innerEventId Remove events by event id.
92      * @param param Remove events by value of param.
93      */
94     void Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId, int64_t param);
95 
96     /**
97      * Remove events with specified requirements.
98      *
99      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
100      * @param name Remove events by name of the task.
101      */
102     void Remove(const std::shared_ptr<EventHandler> &owner, const std::string &name);
103 
104     /**
105      * Add file descriptor listener for a file descriptor.
106      *
107      * @param fileDescriptor File descriptor.
108      * @param events Events from file descriptor, such as input, output, error
109      * @param listener Listener callback.
110      * @return Return 'ERR_OK' on success.
111      */
112     ErrCode AddFileDescriptorListener(
113         int32_t fileDescriptor, uint32_t events, const std::shared_ptr<FileDescriptorListener> &listener);
114 
115     /**
116      * Remove all file descriptor listeners for a specified owner.
117      *
118      * @param owner Owner of the event which is point to an instance of 'FileDescriptorListener'.
119      */
120     void RemoveFileDescriptorListener(const std::shared_ptr<EventHandler> &owner);
121 
122     /**
123      * Remove file descriptor listener for a file descriptor.
124      *
125      * @param fileDescriptor File descriptor.
126      */
127     void RemoveFileDescriptorListener(int32_t fileDescriptor);
128 
129     /**
130      * Prepare event queue, before calling {@link #GetEvent}.
131      * If {@link #Finish} is called, prepare event queue again, before calling {@link #GetEvent}.
132      */
133     void Prepare();
134 
135     /**
136      * Exit from blocking in {@link #GetEvent}, and mark the event queue finished.
137      * After calling {@link #Finish}, {@link #GetEvent} never returns any event, until {@link #Prepare} is called.
138      */
139     void Finish();
140 
141     /**
142      * Get event from event queue one by one.
143      * Before calling this method, developers should call {@link #Prepare} first.
144      * If none should be handled right now, the thread will be blocked in this method.
145      * Call {@link #Finish} to exit from blocking.
146      *
147      * @return Returns nullptr if event queue is not prepared yet, or {@link #Finish} is called.
148      * Otherwise returns event instance.
149      */
150     InnerEvent::Pointer GetEvent();
151 
152     /**
153      * Get expired event from event queue one by one.
154      * Before calling this method, developers should call {@link #Prepare} first.
155      *
156      * @param nextExpiredTime Output the expired time for the next event.
157      * @return Returns nullptr if none in event queue is expired.
158      * Otherwise returns event instance.
159      */
160     InnerEvent::Pointer GetExpiredEvent(InnerEvent::TimePoint &nextExpiredTime);
161 
162     /**
163      * Prints out the internal information about an object in the specified format,
164      * helping you diagnose internal errors of the object.
165      *
166      * @param dumpr The Dumper object you have implemented to process the output internal information.
167      */
168     void Dump(Dumper &dumper);
169 
170     /**
171      * Print out the internal information about an object in the specified format,
172      * helping you diagnose internal errors of the object.
173      *
174      * @param queueInfo queue Info.
175      */
176     void DumpQueueInfo(std::string& queueInfo);
177 
178     /**
179      * Checks whether the current EventHandler is idle.
180      *
181      * @return Returns true if all events have been processed; returns false otherwise.
182      */
183     bool IsIdle();
184 
185     /**
186      * Check whether this event queue is empty.
187      *
188      * @return If queue is empty return true otherwise return false.
189      */
190     bool IsQueueEmpty();
191 
192     /**
193      * Check whether an event with the given ID can be found among the events that have been sent but not processed.
194      *
195      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
196      * @param innerEventId The id of the event.
197      */
198     bool HasInnerEvent(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId);
199 
200     /**
201      * Check whether an event carrying the given param can be found among the events that have been sent but not
202      * processed.
203      *
204      * @param owner The owner of the event which is point to an instance of 'EventHandler'.
205      * @param param The basic parameter of the event.
206      */
207     bool HasInnerEvent(const std::shared_ptr<EventHandler> &owner, int64_t param);
208 
209 private:
210     using RemoveFilter = std::function<bool(const InnerEvent::Pointer &)>;
211     using HasFilter = std::function<bool(const InnerEvent::Pointer &)>;
212 
213     /*
214      * To avoid starvation of lower priority event queue, give a chance to process lower priority events,
215      * after continuous processing several higher priority events.
216      */
217     static const uint32_t DEFAULT_MAX_HANDLED_EVENT_COUNT = 5;
218 
219     // Sub event queues for IMMEDIATE, HIGH and LOW priority. So use value of IDLE as size.
220     static const uint32_t SUB_EVENT_QUEUE_NUM = static_cast<uint32_t>(Priority::IDLE);
221 
222     struct SubEventQueue {
223         std::list<InnerEvent::Pointer> queue;
224         uint32_t handledEventsCount{0};
225         uint32_t maxHandledEventsCount{DEFAULT_MAX_HANDLED_EVENT_COUNT};
226     };
227 
228     void Remove(const RemoveFilter &filter);
229     bool HasInnerEvent(const HasFilter &filter);
230     InnerEvent::Pointer PickEventLocked(const InnerEvent::TimePoint &now, InnerEvent::TimePoint &nextWakeUpTime);
231     InnerEvent::Pointer GetExpiredEventLocked(InnerEvent::TimePoint &nextExpiredTime);
232     void WaitUntilLocked(const InnerEvent::TimePoint &when, std::unique_lock<std::mutex> &lock);
233     void HandleFileDescriptorEvent(int32_t fileDescriptor, uint32_t events);
234     bool EnsureIoWaiterSupportListerningFileDescriptorLocked();
235 
236     std::mutex queueLock_;
237 
238     std::atomic_bool usable_ {true};
239 
240     // Sub event queues for different priority.
241     std::array<SubEventQueue, SUB_EVENT_QUEUE_NUM> subEventQueues_;
242 
243     // Event queue for IDLE events.
244     std::list<InnerEvent::Pointer> idleEvents_;
245 
246     // Next wake up time when block in 'GetEvent'.
247     InnerEvent::TimePoint wakeUpTime_ { InnerEvent::TimePoint::max() };
248 
249     // Mark if in idle mode, and record the start time of idle.
250     InnerEvent::TimePoint idleTimeStamp_ { InnerEvent::Clock::now() };
251 
252     bool isIdle_ {true};
253 
254     // Mark if the event queue is finished.
255     bool finished_ {true};
256 
257     // IO waiter used to block if no events while calling 'GetEvent'.
258     std::shared_ptr<IoWaiter> ioWaiter_;
259 
260     // File descriptor listeners to handle IO events.
261     std::map<int32_t, std::shared_ptr<FileDescriptorListener>> listeners_;
262 };
263 }  // namespace AppExecFwk
264 }  // namespace OHOS
265 
266 #endif  // #ifndef BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H
267