• 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 <atomic>
21 #include <functional>
22 #include <list>
23 #include <map>
24 #include <mutex>
25 
26 #include "inner_event.h"
27 #include "event_handler_errors.h"
28 #include "file_descriptor_listener.h"
29 #include "dumper.h"
30 
31 namespace OHOS {
32 namespace AppExecFwk {
33 class IoWaiter;
34 class EventHandler;
35 class DeamonIoWaiter;
36 struct PendingTaskInfo;
37 
38 enum class EventInsertType: uint32_t {
39     // Insert event at end
40     AT_END = 0,
41     // Insert event at front
42     AT_FRONT
43 };
44 
45 enum class Observer {
46     ARKTS_GC,
47 };
48 
49 enum class EventRunnerStage {
50     // enter loop
51     STAGE_ENTRY_RUNNER = 1<<0,
52     // exit loop
53     STAGE_EXIT_RUNNER = 1<<1,
54     // waiting
55     STAGE_BEFORE_WAITING = 1<<2,
56     // recover form sleeping
57     STAGE_AFTER_WAITING = 1<<3,
58     // insert vip task
59     STAGE_VIP_EXISTED = 1<<4,
60     // current queue not exists vip task
61     STAGE_VIP_NONE = 1<<5,
62     // invaild key
63     STAGE_INVAILD = 0,
64 };
65 
66 struct StageInfo {
67     // STAGE_BEFORE_WAITING, timesteap
68     int64_t timestamp;
69     // STAGE_BEFORE_WAITING, milliseconds
70     int32_t sleepTime;
71     // STAGE_AFTER_WAITING
72     int reason;
73 };
74 
75 using EventRunnerObserverCallBack = std::function<int(EventRunnerStage stage, const StageInfo* info)>;
76 
77 struct EventRunnerObserver {
78     Observer observer;
79     uint32_t stages;
80     EventRunnerObserverCallBack notifyCb;
ClearObserverEventRunnerObserver81     void ClearObserver()
82     {
83         stages = static_cast<uint32_t>(EventRunnerStage::STAGE_INVAILD);
84         notifyCb = nullptr;
85     }
86 };
87 
88 struct ObserverTrace {
89     std::string source;
90     std::string stage;
ObserverTraceObserverTrace91     ObserverTrace() {};
ObserverTraceObserverTrace92     ObserverTrace(std::string currentSource, std::string currentStage)
93         : source(currentSource), stage(currentStage) {}
getTraceInfoObserverTrace94     std::string getTraceInfo()
95     {
96         std::string traceInfo;
97         traceInfo.append("Et-obs:");
98         if (stage.empty()) {
99             traceInfo.append(" ");
100         } else {
101             traceInfo.append(stage);
102         }
103         traceInfo.append(",");
104         if (!source.empty()) {
105             traceInfo.append(source);
106         }
107         return traceInfo;
108     }
109 };
110 
111 class EventQueue {
112 public:
113     // Priority for the events
114     enum class Priority : uint32_t {
115         // The highest priority queue, should be distributed until the tasks in the queue are completed.
116         VIP = 0,
117         // Event that should be distributed at once if possible.
118         IMMEDIATE,
119         // High priority event, sorted by handle time, should be distributed before low priority event.
120         HIGH,
121         // Normal event, sorted by handle time.
122         LOW,
123         // Event that should be distributed only if no other event right now.
124         IDLE,
125     };
126 
127     EventQueue();
128     explicit EventQueue(const std::shared_ptr<IoWaiter> &ioWaiter);
129     virtual ~EventQueue();
130     DISALLOW_COPY_AND_MOVE(EventQueue);
131 
132     /**
133      * Insert an event into event queue with different priority.
134      * The events will be sorted by handle time.
135      *
136      * @param event Event instance which should be added into event queue.
137      * @param Priority Priority of the event
138      * @param insertType The type of insertint event to queue
139      *
140      * @see #Priority
141      */
142     virtual bool Insert(InnerEvent::Pointer &event, Priority priority = Priority::LOW,
143         EventInsertType insertType = EventInsertType::AT_END, bool noBarrier = false) = 0;
144 
145     /**
146      * Remove events if its owner is invalid, for base queue.
147      */
RemoveOrphan()148     virtual void RemoveOrphan() {};
149 
150     /**
151      * Remove events if its owner is invalid, for ffrt queue.
152      */
RemoveOrphanByHandlerId(const std::string & handlerId)153     virtual void RemoveOrphanByHandlerId(const std::string& handlerId) { (void)handlerId; };
154 
155     /**
156      * Remove all events.
157      */
158     virtual void RemoveAll() = 0;
159 
160     /**
161      * Remove events with specified requirements.
162      *
163      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
164      */
165     virtual void Remove(const std::shared_ptr<EventHandler> &owner) = 0;
166 
167     /**
168      * Remove events with specified requirements.
169      *
170      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
171      * @param innerEventId Remove events by event id.
172      */
173     virtual void Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId) = 0;
174 
175     /**
176      * Remove events with specified requirements.
177      *
178      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
179      * @param innerEventId Remove events by event id.
180      * @param param Remove events by value of param.
181      */
182     virtual void Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId, int64_t param) = 0;
183 
184     /**
185      * Remove events with specified requirements.
186      *
187      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
188      * @param name Remove events by name of the task.
189      */
190     virtual bool Remove(const std::shared_ptr<EventHandler> &owner, const std::string &name) = 0;
191 
192     /**
193      * Add file descriptor listener for a file descriptor.
194      *
195      * @param fileDescriptor File descriptor.
196      * @param events Events from file descriptor, such as input, output, error
197      * @param listener Listener callback.
198      * @return Return 'ERR_OK' on success.
199      */
200     virtual ErrCode AddFileDescriptorListener(int32_t fileDescriptor, uint32_t events,
201         const std::shared_ptr<FileDescriptorListener> &listener, const std::string &taskName,
202         Priority priority = Priority::HIGH) = 0;
203 
204     /**
205      * Remove all file descriptor listeners for a specified owner.
206      *
207      * @param owner Owner of the event which is point to an instance of 'FileDescriptorListener'.
208      */
209     virtual void RemoveFileDescriptorListener(const std::shared_ptr<EventHandler> &owner) = 0;
210 
211     /**
212      * Remove file descriptor listener for a file descriptor.
213      *
214      * @param fileDescriptor File descriptor.
215      */
216     virtual void RemoveFileDescriptorListener(int32_t fileDescriptor) = 0;
217 
218     /**
219      * Prepare event queue, before calling {@link #GetEvent}.
220      * If {@link #Finish} is called, prepare event queue again, before calling {@link #GetEvent}.
221      */
222     virtual void Prepare() = 0;
223 
224     /**
225      * Exit from blocking in {@link #GetEvent}, and mark the event queue finished.
226      * After calling {@link #Finish}, {@link #GetEvent} never returns any event, until {@link #Prepare} is called.
227      */
228     virtual void Finish() = 0;
229 
230     /**
231      * Get event from event queue one by one.
232      * Before calling this method, developers should call {@link #Prepare} first.
233      * If none should be handled right now, the thread will be blocked in this method.
234      * Call {@link #Finish} to exit from blocking.
235      *
236      * @return Returns nullptr if event queue is not prepared yet, or {@link #Finish} is called.
237      * Otherwise returns event instance.
238      */
239     virtual InnerEvent::Pointer GetEvent();
240 
241     /**
242      * Get expired event from event queue one by one.
243      * Before calling this method, developers should call {@link #Prepare} first.
244      *
245      * @param nextExpiredTime Output the expired time for the next event.
246      * @return Returns nullptr if none in event queue is expired.
247      * Otherwise returns event instance.
248      */
249     virtual InnerEvent::Pointer GetExpiredEvent(InnerEvent::TimePoint &nextExpiredTime);
250 
251     /**
252      * Prints out the internal information about an object in the specified format,
253      * helping you diagnose internal errors of the object.
254      *
255      * @param dumper The Dumper object you have implemented to process the output internal information.
256      */
257     virtual void Dump(Dumper &dumper) = 0;
258 
259     /**
260      * Print out the internal information about an object in the specified format,
261      * helping you diagnose internal errors of the object.
262      *
263      * @param queueInfo queue Info.
264      */
265     virtual void DumpQueueInfo(std::string& queueInfo) = 0;
266 
267     /**
268      * Checks whether the current EventHandler is idle.
269      *
270      * @return Returns true if all events have been processed; returns false otherwise.
271      */
272     virtual bool IsIdle() = 0;
273 
274     /**
275      * Check whether this event queue is empty.
276      *
277      * @return If queue is empty return true otherwise return false.
278      */
279     virtual bool IsQueueEmpty() = 0;
280 
281     /**
282      * Check whether an event with the given ID can be found among the events that have been sent but not processed.
283      *
284      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
285      * @param innerEventId The id of the event.
286      */
287     virtual bool HasInnerEvent(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId) = 0;
288 
289     /**
290      * Check whether an event carrying the given param can be found among the events that have been sent but not
291      * processed.
292      *
293      * @param owner The owner of the event which is point to an instance of 'EventHandler'.
294      * @param param The basic parameter of the event.
295      */
296     virtual bool HasInnerEvent(const std::shared_ptr<EventHandler> &owner, int64_t param) = 0;
297 
PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer & event)298     virtual void PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer &event) { (void)event; }
299 
PushHistoryQueueAfterDistribute()300     virtual void PushHistoryQueueAfterDistribute() {}
301 
302     virtual bool HasPreferEvent(int basePrio) = 0;
303 
304     virtual std::string DumpCurrentQueueSize() = 0;
305 
306     /**
307      * Check whether there are currenty file descriptors is need to be processed.
308      */
309     void CheckFileDescriptorEvent();
310 
311     /**
312      * Set waiter mode, true for deamon io waiter
313      */
SetIoWaiter(bool useDeamonIoWaiter)314     void SetIoWaiter(bool useDeamonIoWaiter)
315     {
316         useDeamonIoWaiter_ = useDeamonIoWaiter;
317     }
318 
319     /**
320      * Get ffrt queue handler type, only for ffrt thread mode.
321      */
GetFfrtQueue()322     virtual void* GetFfrtQueue() { return nullptr; }
323 
324     /**
325      * Insert task to ffrt queue, and wait to handled, only for ffrt thread mode.
326      */
327     virtual bool InsertSyncEvent(InnerEvent::Pointer &event, Priority priority = Priority::LOW,
328         EventInsertType insertType = EventInsertType::AT_END)
329     {
330         (void)event;
331         (void)priority;
332         (void)insertType;
333         return true;
334     }
335 
336     /**
337      * Get pending task info
338      */
339     virtual PendingTaskInfo QueryPendingTaskInfo(int32_t fileDescriptor) = 0;
340     /**
341      * add observer
342      *
343      * @param observer runner observer.
344      * @param stages The stages of observer
345      * @param callback observer callback.
346      */
AddObserver(Observer observer,uint32_t stages,EventRunnerObserverCallBack callback)347     void AddObserver(Observer observer, uint32_t stages, EventRunnerObserverCallBack callback)
348     {
349         observer_.observer = observer;
350         observer_.notifyCb = callback;
351         observer_.stages = stages;
352     }
353 
354     /**
355      * Cancel And Wait
356      */
357     virtual void CancelAndWait() = 0;
358 
359     /**
360      * notify GC Observer vip events finished
361      */
362     virtual void NotifyObserverVipDone(const InnerEvent::Pointer &event);
363 
364     /**
365      * Get the first event handle time in the prioritized task queue.
366      *
367      * @param priority The specified priority.
368      */
369     virtual inline uint64_t GetQueueFirstEventHandleTime(int32_t priority) = 0;
370 
371     /**
372      * Set the lazy mode for AppVsync
373      */
374     void SetVsyncLazyMode(bool isLazy);
375 
376     /**
377      * Set the waiter of AppVsync
378      */
379     void SetVsyncWaiter(bool isDaemon);
380 
381     /**
382      * the vsync task is comming.
383      */
DispatchVsyncTaskNotify()384     inline void DispatchVsyncTaskNotify()
385     {
386         ++sumOfPendingVsync_;
387         if (epollTimePoint_ < InnerEvent::Clock::now()) {
388             needEpoll_.store(true);
389         }
390     }
391 
392     /**
393      * the vsync task be handled.
394      */
HandleVsyncTaskNotify()395     inline void HandleVsyncTaskNotify()
396     {
397         --sumOfPendingVsync_;
398     }
399 
400     /**
401      * set the barrier mode.
402      */
SetBarrierMode(bool isBarrierMode)403     inline void SetBarrierMode(bool isBarrierMode)
404     {
405         isBarrierMode_ = isBarrierMode;
406         enterBarrierTime_ = !isBarrierMode? UINT64_MAX :
407             static_cast<uint64_t>(InnerEvent::Clock::now().time_since_epoch().count());
408     }
409 
410     /**
411      * get the barrier mode.
412      */
IsBarrierMode()413     inline bool IsBarrierMode()
414     {
415         return isBarrierMode_;
416     }
417 
418 protected:
419     void RemoveInvalidFileDescriptor();
420 
421     /**
422      * Add file descriptor base.
423      *
424      * @param fileDescriptor File descriptor.
425      * @param events Events from file descriptor, such as input, output, error
426      * @param listener Listener callback.
427      * @param taskName task name.
428      * @param Priority Priority of the event.
429      * @return Return result ErrCode.
430      */
431     ErrCode AddFileDescriptorListenerBase(int32_t fileDescriptor, uint32_t events,
432         const std::shared_ptr<FileDescriptorListener> &listener, const std::string &taskName,
433         Priority priority);
434 
435     /**
436      * Add file descriptor by fd.
437      *
438      * @param fileDescriptor File descriptor.
439      * @param events Events from file descriptor, such as input, output, error
440      * @param taskName task name.
441      * @param listener Listener callback.
442      * @param Priority Priority of the event.
443      * @return Return result boolean.
444      */
445     bool AddFileDescriptorByFd(int32_t fileDescriptor, uint32_t events, const std::string &taskName,
446         const std::shared_ptr<FileDescriptorListener>& listener, EventQueue::Priority priority);
447 
448     bool EnsureIoWaiterLocked(const std::shared_ptr<FileDescriptorListener>& listener);
449 
450     /**
451      * handle file descriptor event.
452      *
453      * @param fileDescriptor File descriptor.
454      * @param events Events from file descriptor, such as input, output, error
455      * @param name task name.
456      * @param Priority Priority of the event.
457      */
458     void HandleFileDescriptorEvent(int32_t fileDescriptor, uint32_t events, const std::string &name,
459         Priority priority);
460 
461     /**
462      * remove listener by owner.
463      *
464      * @param owner current eventhandler.
465      */
466     void RemoveListenerByOwner(const std::shared_ptr<EventHandler> &owner);
467 
468     /**
469      * remove listener by fd.
470      *
471      * @param fileDescriptor fd.
472      */
473     void RemoveListenerByFd(int32_t fileDescriptor);
474 
475     void PrepareBase();
476 
477     void FinishBase();
478 
479     void WaitUntilLocked(const InnerEvent::TimePoint &when, std::unique_lock<std::mutex> &lock);
480     std::mutex queueLock_;
481 
482     std::atomic_bool usable_ {true};
483 
484     bool isIdle_ {true};
485 
486     // Mark if the event queue is finished.
487     bool finished_ {true};
488 
489     // IO waiter used to block if no events while calling 'GetEvent'.
490     std::shared_ptr<IoWaiter> ioWaiter_;
491 
492     // select different epoll
493     bool useDeamonIoWaiter_ = false;
494 
495     // File descriptor listeners to handle IO events.
496     std::map<int32_t, std::shared_ptr<FileDescriptorListener>> listeners_;
497 
498     EventRunnerObserver observer_ = {.stages = static_cast<uint32_t>(EventRunnerStage::STAGE_INVAILD),
499         .notifyCb = nullptr};
500 
501     std::atomic_int8_t sumOfPendingVsync_ = 0;
502     std::atomic_bool needEpoll_ = true;
503     std::atomic_bool isLazyMode_ = true;
504     bool isBarrierMode_ = false;
505     bool isVsyncOnDaemon_ = true;
506     Priority vsyncPriority_ = Priority::VIP;
507     InnerEvent::TimePoint epollTimePoint_;
508     uint64_t enterBarrierTime_ = UINT64_MAX;
509 };
510 }  // namespace AppExecFwk
511 }  // namespace OHOS
512 
513 #endif  // #ifndef BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H
514