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