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