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 <functional>
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 
30 namespace OHOS {
31 namespace AppExecFwk {
32 class IoWaiter;
33 class EventHandler;
34 class DeamonIoWaiter;
35 struct PendingTaskInfo;
36 
37 enum class EventInsertType: uint32_t {
38     // Insert event at end
39     AT_END = 0,
40     // Insert event at front
41     AT_FRONT
42 };
43 
44 enum class Observer {
45     ARKTS_GC,
46 };
47 
48 enum class EventRunnerStage {
49     // enter loop
50     STAGE_ENTRY_RUNNER = 1<<0,
51     // exit loop
52     STAGE_EXIT_RUNNER = 1<<1,
53     // waiting
54     STAGE_BEFORE_WAITING = 1<<2,
55     // recover form sleeping
56     STAGE_AFTER_WAITING = 1<<3,
57     // invaild key
58     STAGE_INVAILD = 0,
59 };
60 
61 struct StageInfo {
62     // STAGE_BEFORE_WAITING, timesteap
63     int64_t timestamp;
64     // STAGE_BEFORE_WAITING, milliseconds
65     int32_t sleepTime;
66     // STAGE_AFTER_WAITING
67     int reason;
68 };
69 
70 using EventRunnerObserverCallBack = std::function<int(EventRunnerStage stage, const StageInfo* info)>;
71 
72 struct EventRunnerObserver {
73     Observer observer;
74     uint32_t stages;
75     EventRunnerObserverCallBack notifyCb;
ClearObserverEventRunnerObserver76     void ClearObserver()
77     {
78         stages = static_cast<uint32_t>(EventRunnerStage::STAGE_INVAILD);
79         notifyCb = nullptr;
80     }
81 };
82 
83 struct ObserverTrace {
84     std::string source;
85     std::string stage;
ObserverTraceObserverTrace86     ObserverTrace() {};
ObserverTraceObserverTrace87     ObserverTrace(std::string currentSource, std::string currentStage)
88         : source(currentSource), stage(currentStage) {}
getTraceInfoObserverTrace89     std::string getTraceInfo()
90     {
91         std::string traceInfo;
92         traceInfo.append("Et-obs:");
93         if (stage.empty()) {
94             traceInfo.append(" ");
95         } else {
96             traceInfo.append(stage);
97         }
98         traceInfo.append(",");
99         if (!source.empty()) {
100             traceInfo.append(source);
101         }
102         return traceInfo;
103     }
104 };
105 
106 class EventQueue {
107 public:
108     // Priority for the events
109     enum class Priority : uint32_t {
110         // The highest priority queue, should be distributed until the tasks in the queue are completed.
111         VIP = 0,
112         // Event that should be distributed at once if possible.
113         IMMEDIATE,
114         // High priority event, sorted by handle time, should be distributed before low priority event.
115         HIGH,
116         // Normal event, sorted by handle time.
117         LOW,
118         // Event that should be distributed only if no other event right now.
119         IDLE,
120     };
121 
122     EventQueue();
123     explicit EventQueue(const std::shared_ptr<IoWaiter> &ioWaiter);
124     virtual ~EventQueue();
125     DISALLOW_COPY_AND_MOVE(EventQueue);
126 
127     /**
128      * Insert an event into event queue with different priority.
129      * The events will be sorted by handle time.
130      *
131      * @param event Event instance which should be added into event queue.
132      * @param Priority Priority of the event
133      * @param insertType The type of insertint event to queue
134      *
135      * @see #Priority
136      */
137     virtual void Insert(InnerEvent::Pointer &event, Priority priority = Priority::LOW,
138         EventInsertType insertType = EventInsertType::AT_END) = 0;
139 
140     /**
141      * Remove events if its owner is invalid, for base queue.
142      */
RemoveOrphan()143     virtual void RemoveOrphan() {};
144 
145     /**
146      * Remove events if its owner is invalid, for ffrt queue.
147      */
RemoveOrphanByHandlerId(const std::string & handlerId)148     virtual void RemoveOrphanByHandlerId(const std::string& handlerId) { (void)handlerId; };
149 
150     /**
151      * Remove all events.
152      */
153     virtual void RemoveAll() = 0;
154 
155     /**
156      * Remove events with specified requirements.
157      *
158      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
159      */
160     virtual void Remove(const std::shared_ptr<EventHandler> &owner) = 0;
161 
162     /**
163      * Remove events with specified requirements.
164      *
165      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
166      * @param innerEventId Remove events by event id.
167      */
168     virtual void Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId) = 0;
169 
170     /**
171      * Remove events with specified requirements.
172      *
173      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
174      * @param innerEventId Remove events by event id.
175      * @param param Remove events by value of param.
176      */
177     virtual void Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId, int64_t param) = 0;
178 
179     /**
180      * Remove events with specified requirements.
181      *
182      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
183      * @param name Remove events by name of the task.
184      */
185     virtual bool Remove(const std::shared_ptr<EventHandler> &owner, const std::string &name) = 0;
186 
187     /**
188      * Add file descriptor listener for a file descriptor.
189      *
190      * @param fileDescriptor File descriptor.
191      * @param events Events from file descriptor, such as input, output, error
192      * @param listener Listener callback.
193      * @return Return 'ERR_OK' on success.
194      */
195     ErrCode AddFileDescriptorListener(int32_t fileDescriptor, uint32_t events,
196         const std::shared_ptr<FileDescriptorListener> &listener, const std::string &taskName,
197         Priority priority = Priority::HIGH);
198 
199     /**
200      * Remove all file descriptor listeners for a specified owner.
201      *
202      * @param owner Owner of the event which is point to an instance of 'FileDescriptorListener'.
203      */
204     void RemoveFileDescriptorListener(const std::shared_ptr<EventHandler> &owner);
205 
206     /**
207      * Remove file descriptor listener for a file descriptor.
208      *
209      * @param fileDescriptor File descriptor.
210      */
211     void RemoveFileDescriptorListener(int32_t fileDescriptor);
212 
213     /**
214      * Prepare event queue, before calling {@link #GetEvent}.
215      * If {@link #Finish} is called, prepare event queue again, before calling {@link #GetEvent}.
216      */
217     void Prepare();
218 
219     /**
220      * Exit from blocking in {@link #GetEvent}, and mark the event queue finished.
221      * After calling {@link #Finish}, {@link #GetEvent} never returns any event, until {@link #Prepare} is called.
222      */
223     void Finish();
224 
225     /**
226      * Get event from event queue one by one.
227      * Before calling this method, developers should call {@link #Prepare} first.
228      * If none should be handled right now, the thread will be blocked in this method.
229      * Call {@link #Finish} to exit from blocking.
230      *
231      * @return Returns nullptr if event queue is not prepared yet, or {@link #Finish} is called.
232      * Otherwise returns event instance.
233      */
234     virtual InnerEvent::Pointer GetEvent();
235 
236     /**
237      * Get expired event from event queue one by one.
238      * Before calling this method, developers should call {@link #Prepare} first.
239      *
240      * @param nextExpiredTime Output the expired time for the next event.
241      * @return Returns nullptr if none in event queue is expired.
242      * Otherwise returns event instance.
243      */
244     virtual InnerEvent::Pointer GetExpiredEvent(InnerEvent::TimePoint &nextExpiredTime);
245 
246     /**
247      * Prints out the internal information about an object in the specified format,
248      * helping you diagnose internal errors of the object.
249      *
250      * @param dumper The Dumper object you have implemented to process the output internal information.
251      */
252     virtual void Dump(Dumper &dumper) = 0;
253 
254     /**
255      * Print out the internal information about an object in the specified format,
256      * helping you diagnose internal errors of the object.
257      *
258      * @param queueInfo queue Info.
259      */
260     virtual void DumpQueueInfo(std::string& queueInfo) = 0;
261 
262     /**
263      * Checks whether the current EventHandler is idle.
264      *
265      * @return Returns true if all events have been processed; returns false otherwise.
266      */
267     virtual bool IsIdle() = 0;
268 
269     /**
270      * Check whether this event queue is empty.
271      *
272      * @return If queue is empty return true otherwise return false.
273      */
274     virtual bool IsQueueEmpty() = 0;
275 
276     /**
277      * Check whether an event with the given ID can be found among the events that have been sent but not processed.
278      *
279      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
280      * @param innerEventId The id of the event.
281      */
282     virtual bool HasInnerEvent(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId) = 0;
283 
284     /**
285      * Check whether an event carrying the given param can be found among the events that have been sent but not
286      * processed.
287      *
288      * @param owner The owner of the event which is point to an instance of 'EventHandler'.
289      * @param param The basic parameter of the event.
290      */
291     virtual bool HasInnerEvent(const std::shared_ptr<EventHandler> &owner, int64_t param) = 0;
292 
PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer & event)293     virtual void PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer &event) { (void)event; }
294 
PushHistoryQueueAfterDistribute()295     virtual void PushHistoryQueueAfterDistribute() {}
296 
297     virtual bool HasPreferEvent(int basePrio) = 0;
298 
299     virtual std::string DumpCurrentQueueSize() = 0;
300 
301     /**
302      * Check whether there are currenty file descriptors is need to be processed.
303      */
304     void CheckFileDescriptorEvent();
305 
306     /**
307      * Set waiter mode, true for deamon io waiter
308      */
SetIoWaiter(bool useDeamonIoWaiter)309     void SetIoWaiter(bool useDeamonIoWaiter)
310     {
311         useDeamonIoWaiter_ = useDeamonIoWaiter;
312     }
313 
314     /**
315      * Get ffrt queue handler type, only for ffrt thread mode.
316      */
GetFfrtQueue()317     virtual void* GetFfrtQueue() { return nullptr; }
318 
319     /**
320      * Insert task to ffrt queue, and wait to handled, only for ffrt thread mode.
321      */
322     virtual void InsertSyncEvent(InnerEvent::Pointer &event, Priority priority = Priority::LOW,
323         EventInsertType insertType = EventInsertType::AT_END)
324     {
325         (void)event;
326         (void)priority;
327         (void)insertType;
328     }
329 
330     /**
331      * Get pending task info
332      */
333     virtual PendingTaskInfo QueryPendingTaskInfo(int32_t fileDescriptor) = 0;
334     /**
335      * add observer
336      *
337      * @param observer runner observer.
338      * @param stages The stages of observer
339      * @param callback observer callback.
340      */
AddObserver(Observer observer,uint32_t stages,EventRunnerObserverCallBack callback)341     void AddObserver(Observer observer, uint32_t stages, EventRunnerObserverCallBack callback)
342     {
343         observer_.observer = observer;
344         observer_.notifyCb = callback;
345         observer_.stages = stages;
346     }
347 
348     /**
349      * Cancel And Wait
350      */
351     virtual void CancelAndWait() = 0;
352 
353 private:
354 
355     void HandleFileDescriptorEvent(int32_t fileDescriptor, uint32_t events, const std::string &name,
356         Priority priority);
357     bool EnsureIoWaiterSupportListerningFileDescriptorLocked();
358     bool AddFileDescriptorByFd(int32_t fileDescriptor, uint32_t events, const std::string &taskName,
359         const std::shared_ptr<FileDescriptorListener>& listener, EventQueue::Priority priority);
360 protected:
361     void RemoveInvalidFileDescriptor();
362     void WaitUntilLocked(const InnerEvent::TimePoint &when, std::unique_lock<std::mutex> &lock);
363 
364     std::mutex queueLock_;
365 
366     std::atomic_bool usable_ {true};
367 
368     bool isIdle_ {true};
369 
370     // Mark if the event queue is finished.
371     bool finished_ {true};
372 
373     // IO waiter used to block if no events while calling 'GetEvent'.
374     std::shared_ptr<IoWaiter> ioWaiter_;
375 
376     // select different epoll
377     bool useDeamonIoWaiter_ = false;
378 
379     // File descriptor listeners to handle IO events.
380     std::map<int32_t, std::shared_ptr<FileDescriptorListener>> listeners_;
381 
382     EventRunnerObserver observer_ = {.stages = static_cast<uint32_t>(EventRunnerStage::STAGE_INVAILD),
383         .notifyCb = nullptr};
384 };
385 }  // namespace AppExecFwk
386 }  // namespace OHOS
387 
388 #endif  // #ifndef BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H
389