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 #include "event_queue.h"
17 
18 #include <algorithm>
19 
20 #include "epoll_io_waiter.h"
21 #include "event_handler.h"
22 #include "event_handler_utils.h"
23 #include "none_io_waiter.h"
24 
25 DEFINE_HILOG_LABEL("EventQueue");
26 
27 namespace OHOS {
28 namespace AppExecFwk {
29 namespace {
30 // Help to insert events into the event queue sorted by handle time.
InsertEventsLocked(std::list<InnerEvent::Pointer> & events,InnerEvent::Pointer & event)31 inline void InsertEventsLocked(std::list<InnerEvent::Pointer> &events, InnerEvent::Pointer &event)
32 {
33     auto f = [](const InnerEvent::Pointer &first, const InnerEvent::Pointer &second) {
34         if (!first || !second) {
35             return false;
36         }
37         return first->GetHandleTime() < second->GetHandleTime();
38     };
39     auto it = std::upper_bound(events.begin(), events.end(), event, f);
40     events.insert(it, std::move(event));
41 }
42 
43 // Help to remove file descriptor listeners.
44 template<typename T>
RemoveFileDescriptorListenerLocked(std::map<int32_t,std::shared_ptr<FileDescriptorListener>> & listeners,const std::shared_ptr<IoWaiter> & ioWaiter,const T & filter)45 void RemoveFileDescriptorListenerLocked(std::map<int32_t, std::shared_ptr<FileDescriptorListener>> &listeners,
46     const std::shared_ptr<IoWaiter> &ioWaiter, const T &filter)
47 {
48     if (!ioWaiter) {
49         return;
50     }
51     for (auto it = listeners.begin(); it != listeners.end();) {
52         if (filter(it->second)) {
53             ioWaiter->RemoveFileDescriptor(it->first);
54             it = listeners.erase(it);
55         } else {
56             ++it;
57         }
58     }
59 }
60 
61 // Help to check whether there is a valid event in list and update wake up time.
CheckEventInListLocked(const std::list<InnerEvent::Pointer> & events,const InnerEvent::TimePoint & now,InnerEvent::TimePoint & nextWakeUpTime)62 inline bool CheckEventInListLocked(const std::list<InnerEvent::Pointer> &events, const InnerEvent::TimePoint &now,
63     InnerEvent::TimePoint &nextWakeUpTime)
64 {
65     if (!events.empty()) {
66         const auto &handleTime = events.front()->GetHandleTime();
67         if (handleTime < nextWakeUpTime) {
68             nextWakeUpTime = handleTime;
69             return handleTime <= now;
70         }
71     }
72 
73     return false;
74 }
75 
PopFrontEventFromListLocked(std::list<InnerEvent::Pointer> & events)76 inline InnerEvent::Pointer PopFrontEventFromListLocked(std::list<InnerEvent::Pointer> &events)
77 {
78     InnerEvent::Pointer event = std::move(events.front());
79     events.pop_front();
80     return event;
81 }
82 }  // unnamed namespace
83 
EventQueue()84 EventQueue::EventQueue() : ioWaiter_(std::make_shared<NoneIoWaiter>())
85 {}
86 
EventQueue(const std::shared_ptr<IoWaiter> & ioWaiter)87 EventQueue::EventQueue(const std::shared_ptr<IoWaiter> &ioWaiter)
88     : ioWaiter_(ioWaiter ? ioWaiter : std::make_shared<NoneIoWaiter>())
89 {
90     if (ioWaiter_->SupportListeningFileDescriptor()) {
91         // Set callback to handle events from file descriptors.
92         ioWaiter_->SetFileDescriptorEventCallback(
93             std::bind(&EventQueue::HandleFileDescriptorEvent, this, std::placeholders::_1, std::placeholders::_2));
94     }
95 }
96 
~EventQueue()97 EventQueue::~EventQueue()
98 {
99     std::lock_guard<std::mutex> lock(queueLock_);
100     usable_.store(false);
101 }
102 
Insert(InnerEvent::Pointer & event,Priority priority)103 void EventQueue::Insert(InnerEvent::Pointer &event, Priority priority)
104 {
105     if (!event) {
106         HILOGE("Insert: Could not insert an invalid event");
107         return;
108     }
109 
110     std::lock_guard<std::mutex> lock(queueLock_);
111     if (!usable_.load()) {
112         return;
113     }
114     bool needNotify = false;
115     switch (priority) {
116         case Priority::IMMEDIATE:
117         case Priority::HIGH:
118         case Priority::LOW: {
119             needNotify = (event->GetHandleTime() < wakeUpTime_);
120             InsertEventsLocked(subEventQueues_[static_cast<uint32_t>(priority)].queue, event);
121             break;
122         }
123         case Priority::IDLE: {
124             // Never wake up thread if insert an idle event.
125             InsertEventsLocked(idleEvents_, event);
126             break;
127         }
128         default:
129             break;
130     }
131 
132     if (needNotify) {
133         ioWaiter_->NotifyOne();
134     }
135 }
136 
RemoveOrphan()137 void EventQueue::RemoveOrphan()
138 {
139     // Remove all events which lost its owner.
140     auto filter = [](const InnerEvent::Pointer &p) { return !p->GetOwner(); };
141 
142     Remove(filter);
143 
144     // Remove all listeners which lost its owner.
145     auto listenerFilter = [](const std::shared_ptr<FileDescriptorListener> &listener) {
146         if (!listener) {
147             return true;
148         }
149         return !listener->GetOwner();
150     };
151 
152     std::lock_guard<std::mutex> lock(queueLock_);
153     if (!usable_.load()) {
154         return;
155     }
156     RemoveFileDescriptorListenerLocked(listeners_, ioWaiter_, listenerFilter);
157 }
158 
Remove(const std::shared_ptr<EventHandler> & owner)159 void EventQueue::Remove(const std::shared_ptr<EventHandler> &owner)
160 {
161     if (!owner) {
162         HILOGE("Remove: Invalid owner");
163         return;
164     }
165 
166     auto filter = [&owner](const InnerEvent::Pointer &p) { return (p->GetOwner() == owner); };
167 
168     Remove(filter);
169 }
170 
Remove(const std::shared_ptr<EventHandler> & owner,uint32_t innerEventId)171 void EventQueue::Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId)
172 {
173     if (!owner) {
174         HILOGE("Remove: Invalid owner");
175         return;
176     }
177 
178     auto filter = [&owner, innerEventId](const InnerEvent::Pointer &p) {
179         return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId);
180     };
181 
182     Remove(filter);
183 }
184 
Remove(const std::shared_ptr<EventHandler> & owner,uint32_t innerEventId,int64_t param)185 void EventQueue::Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId, int64_t param)
186 {
187     if (!owner) {
188         HILOGE("Remove: Invalid owner");
189         return;
190     }
191 
192     auto filter = [&owner, innerEventId, param](const InnerEvent::Pointer &p) {
193         return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId) &&
194                (p->GetParam() == param);
195     };
196 
197     Remove(filter);
198 }
199 
Remove(const std::shared_ptr<EventHandler> & owner,const std::string & name)200 void EventQueue::Remove(const std::shared_ptr<EventHandler> &owner, const std::string &name)
201 {
202     if ((!owner) || (name.empty())) {
203         HILOGE("Remove: Invalid owner or task name");
204         return;
205     }
206 
207     auto filter = [&owner, &name](const InnerEvent::Pointer &p) {
208         return (p->HasTask()) && (p->GetOwner() == owner) && (p->GetTaskName() == name);
209     };
210 
211     Remove(filter);
212 }
213 
Remove(const RemoveFilter & filter)214 void EventQueue::Remove(const RemoveFilter &filter)
215 {
216     std::lock_guard<std::mutex> lock(queueLock_);
217     if (!usable_.load()) {
218         return;
219     }
220     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
221         subEventQueues_[i].queue.remove_if(filter);
222     }
223     idleEvents_.remove_if(filter);
224 }
225 
HasInnerEvent(const std::shared_ptr<EventHandler> & owner,uint32_t innerEventId)226 bool EventQueue::HasInnerEvent(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId)
227 {
228     if (!owner) {
229         HILOGE("HasInnerEvent: Invalid owner");
230         return false;
231     }
232     auto filter = [&owner, innerEventId](const InnerEvent::Pointer &p) {
233         return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId);
234     };
235     return HasInnerEvent(filter);
236 }
237 
HasInnerEvent(const std::shared_ptr<EventHandler> & owner,int64_t param)238 bool EventQueue::HasInnerEvent(const std::shared_ptr<EventHandler> &owner, int64_t param)
239 {
240     if (!owner) {
241         HILOGE("HasInnerEvent: Invalid owner");
242         return false;
243     }
244     auto filter = [&owner, param](const InnerEvent::Pointer &p) {
245         return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetParam() == param);
246     };
247     return HasInnerEvent(filter);
248 }
249 
HasInnerEvent(const HasFilter & filter)250 bool EventQueue::HasInnerEvent(const HasFilter &filter)
251 {
252     std::lock_guard<std::mutex> lock(queueLock_);
253     if (!usable_.load()) {
254         return false;
255     }
256     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
257         std::list<InnerEvent::Pointer>::iterator iter =
258             std::find_if(subEventQueues_[i].queue.begin(), subEventQueues_[i].queue.end(), filter);
259         if (iter != subEventQueues_[i].queue.end()) {
260             return true;
261         }
262     }
263     std::list<InnerEvent::Pointer>::iterator iter = std::find_if(idleEvents_.begin(), idleEvents_.end(), filter);
264     return iter != idleEvents_.end();
265 }
266 
PickEventLocked(const InnerEvent::TimePoint & now,InnerEvent::TimePoint & nextWakeUpTime)267 InnerEvent::Pointer EventQueue::PickEventLocked(const InnerEvent::TimePoint &now, InnerEvent::TimePoint &nextWakeUpTime)
268 {
269     uint32_t priorityIndex = SUB_EVENT_QUEUE_NUM;
270     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
271         // Check whether any event need to be distributed.
272         if (!CheckEventInListLocked(subEventQueues_[i].queue, now, nextWakeUpTime)) {
273             continue;
274         }
275 
276         // Check whether any event in higher priority need to be distributed.
277         if (priorityIndex < SUB_EVENT_QUEUE_NUM) {
278             SubEventQueue &subQueue = subEventQueues_[priorityIndex];
279             // Check whether enough events in higher priority queue are handled continuously.
280             if (subQueue.handledEventsCount < subQueue.maxHandledEventsCount) {
281                 subQueue.handledEventsCount++;
282                 break;
283             }
284         }
285 
286         // Try to pick event from this queue.
287         priorityIndex = i;
288     }
289 
290     if (priorityIndex >= SUB_EVENT_QUEUE_NUM) {
291         // If not found any event to distribute, return nullptr.
292         return InnerEvent::Pointer(nullptr, nullptr);
293     }
294 
295     // Reset handled event count for sub event queues in higher priority.
296     for (uint32_t i = 0; i < priorityIndex; ++i) {
297         subEventQueues_[i].handledEventsCount = 0;
298     }
299 
300     return PopFrontEventFromListLocked(subEventQueues_[priorityIndex].queue);
301 }
302 
GetExpiredEventLocked(InnerEvent::TimePoint & nextExpiredTime)303 InnerEvent::Pointer EventQueue::GetExpiredEventLocked(InnerEvent::TimePoint &nextExpiredTime)
304 {
305     auto now = InnerEvent::Clock::now();
306     wakeUpTime_ = InnerEvent::TimePoint::max();
307     // Find an event which could be distributed right now.
308     InnerEvent::Pointer event = PickEventLocked(now, wakeUpTime_);
309     if (event) {
310         // Exit idle mode, if found an event to distribute.
311         isIdle_ = false;
312         return event;
313     }
314 
315     // If found nothing, enter idle mode and make a time stamp.
316     if (!isIdle_) {
317         idleTimeStamp_ = now;
318         isIdle_ = true;
319     }
320 
321     if (!idleEvents_.empty()) {
322         const auto &idleEvent = idleEvents_.front();
323 
324         // Return the idle event that has been sent before time stamp and reaches its handle time.
325         if ((idleEvent->GetSendTime() <= idleTimeStamp_) && (idleEvent->GetHandleTime() <= now)) {
326             return PopFrontEventFromListLocked(idleEvents_);
327         }
328     }
329 
330     // Update wake up time.
331     nextExpiredTime = wakeUpTime_;
332     return InnerEvent::Pointer(nullptr, nullptr);
333 }
334 
GetEvent()335 InnerEvent::Pointer EventQueue::GetEvent()
336 {
337     std::unique_lock<std::mutex> lock(queueLock_);
338     while (!finished_) {
339         InnerEvent::TimePoint nextWakeUpTime = InnerEvent::TimePoint::max();
340         InnerEvent::Pointer event = GetExpiredEventLocked(nextWakeUpTime);
341         if (event) {
342             return event;
343         }
344         WaitUntilLocked(nextWakeUpTime, lock);
345     }
346 
347     HILOGD("GetEvent: Break out");
348     return InnerEvent::Pointer(nullptr, nullptr);
349 }
350 
GetExpiredEvent(InnerEvent::TimePoint & nextExpiredTime)351 InnerEvent::Pointer EventQueue::GetExpiredEvent(InnerEvent::TimePoint &nextExpiredTime)
352 {
353     std::unique_lock<std::mutex> lock(queueLock_);
354     return GetExpiredEventLocked(nextExpiredTime);
355 }
356 
AddFileDescriptorListener(int32_t fileDescriptor,uint32_t events,const std::shared_ptr<FileDescriptorListener> & listener)357 ErrCode EventQueue::AddFileDescriptorListener(
358     int32_t fileDescriptor, uint32_t events, const std::shared_ptr<FileDescriptorListener> &listener)
359 {
360     if ((fileDescriptor < 0) || ((events & FILE_DESCRIPTOR_EVENTS_MASK) == 0) || (!listener)) {
361         HILOGE("AddFileDescriptorListener(%{public}d, %{public}u, %{public}s): Invalid parameter",
362             fileDescriptor,
363             events,
364             listener ? "valid" : "null");
365         return EVENT_HANDLER_ERR_INVALID_PARAM;
366     }
367 
368     std::lock_guard<std::mutex> lock(queueLock_);
369     if (!usable_.load()) {
370         return EVENT_HANDLER_ERR_NO_EVENT_RUNNER;
371     }
372     auto it = listeners_.find(fileDescriptor);
373     if (it != listeners_.end()) {
374         HILOGE("AddFileDescriptorListener: File descriptor %{public}d is already in listening", fileDescriptor);
375         return EVENT_HANDLER_ERR_FD_ALREADY;
376     }
377 
378     if (!EnsureIoWaiterSupportListerningFileDescriptorLocked()) {
379         return EVENT_HANDLER_ERR_FD_NOT_SUPPORT;
380     }
381 
382     if (!ioWaiter_->AddFileDescriptor(fileDescriptor, events)) {
383         HILOGE("AddFileDescriptorListener: Failed to add file descriptor into IO waiter");
384         return EVENT_HANDLER_ERR_FD_FAILED;
385     }
386 
387     listeners_.emplace(fileDescriptor, listener);
388     return ERR_OK;
389 }
390 
RemoveFileDescriptorListener(const std::shared_ptr<EventHandler> & owner)391 void EventQueue::RemoveFileDescriptorListener(const std::shared_ptr<EventHandler> &owner)
392 {
393     if (!owner) {
394         HILOGE("RemoveFileDescriptorListener: Invalid owner");
395         return;
396     }
397 
398     auto listenerFilter = [&owner](const std::shared_ptr<FileDescriptorListener> &listener) {
399         if (!listener) {
400             return false;
401         }
402         return listener->GetOwner() == owner;
403     };
404 
405     std::lock_guard<std::mutex> lock(queueLock_);
406     if (!usable_.load()) {
407         return;
408     }
409     RemoveFileDescriptorListenerLocked(listeners_, ioWaiter_, listenerFilter);
410 }
411 
RemoveFileDescriptorListener(int32_t fileDescriptor)412 void EventQueue::RemoveFileDescriptorListener(int32_t fileDescriptor)
413 {
414     if (fileDescriptor < 0) {
415         HILOGE("RemoveFileDescriptorListener(%{public}d): Invalid file descriptor", fileDescriptor);
416         return;
417     }
418 
419     std::lock_guard<std::mutex> lock(queueLock_);
420     if (!usable_.load()) {
421         return;
422     }
423     if (listeners_.erase(fileDescriptor) > 0) {
424         ioWaiter_->RemoveFileDescriptor(fileDescriptor);
425     }
426 }
427 
Prepare()428 void EventQueue::Prepare()
429 {
430     std::lock_guard<std::mutex> lock(queueLock_);
431     if (!usable_.load()) {
432         return;
433     }
434     finished_ = false;
435 }
436 
Finish()437 void EventQueue::Finish()
438 {
439     std::lock_guard<std::mutex> lock(queueLock_);
440     if (!usable_.load()) {
441         return;
442     }
443     finished_ = true;
444     ioWaiter_->NotifyAll();
445 }
446 
WaitUntilLocked(const InnerEvent::TimePoint & when,std::unique_lock<std::mutex> & lock)447 void EventQueue::WaitUntilLocked(const InnerEvent::TimePoint &when, std::unique_lock<std::mutex> &lock)
448 {
449     // Get a temp reference of IO waiter, otherwise it maybe released while waiting.
450     auto ioWaiterHolder = ioWaiter_;
451     if (!ioWaiterHolder->WaitFor(lock, TimePointToTimeOut(when))) {
452         HILOGE("WaitUntilLocked: Failed to call wait, reset IO waiter");
453         ioWaiter_ = std::make_shared<NoneIoWaiter>();
454         listeners_.clear();
455     }
456 }
457 
HandleFileDescriptorEvent(int32_t fileDescriptor,uint32_t events)458 void EventQueue::HandleFileDescriptorEvent(int32_t fileDescriptor, uint32_t events)
459 {
460     std::shared_ptr<FileDescriptorListener> listener;
461 
462     {
463         std::lock_guard<std::mutex> lock(queueLock_);
464         if (!usable_.load()) {
465             return;
466         }
467         auto it = listeners_.find(fileDescriptor);
468         if (it == listeners_.end()) {
469             HILOGW("HandleFileDescriptorEvent: Can not found listener, maybe it is removed");
470             return;
471         }
472 
473         // Hold instance of listener.
474         listener = it->second;
475         if (!listener) {
476             return;
477         }
478     }
479 
480     auto handler = listener->GetOwner();
481     if (!handler) {
482         HILOGW("HandleFileDescriptorEvent: Owner of listener is released");
483         return;
484     }
485 
486     std::weak_ptr<FileDescriptorListener> wp = listener;
487     auto f = [fileDescriptor, events, wp]() {
488         auto listener = wp.lock();
489         if (!listener) {
490             HILOGW("HandleFileDescriptorEvent-Lambda: Listener is released");
491             return;
492         }
493 
494         if ((events & FILE_DESCRIPTOR_INPUT_EVENT) != 0) {
495             listener->OnReadable(fileDescriptor);
496         }
497 
498         if ((events & FILE_DESCRIPTOR_OUTPUT_EVENT) != 0) {
499             listener->OnWritable(fileDescriptor);
500         }
501 
502         if ((events & FILE_DESCRIPTOR_SHUTDOWN_EVENT) != 0) {
503             listener->OnShutdown(fileDescriptor);
504         }
505 
506         if ((events & FILE_DESCRIPTOR_EXCEPTION_EVENT) != 0) {
507             listener->OnException(fileDescriptor);
508         }
509     };
510 
511     // Post a high priority task to handle file descriptor events.
512     handler->PostHighPriorityTask(f);
513 }
514 
EnsureIoWaiterSupportListerningFileDescriptorLocked()515 bool EventQueue::EnsureIoWaiterSupportListerningFileDescriptorLocked()
516 {
517     if (ioWaiter_->SupportListeningFileDescriptor()) {
518         return true;
519     }
520 
521     auto newIoWaiter = std::make_shared<EpollIoWaiter>();
522     if (!newIoWaiter->Init()) {
523         HILOGE("EnsureIoWaiterSupportListerningFileDescriptorLocked: Failed to initialize epoll");
524         return false;
525     }
526 
527     // Set callback to handle events from file descriptors.
528     newIoWaiter->SetFileDescriptorEventCallback(
529         std::bind(&EventQueue::HandleFileDescriptorEvent, this, std::placeholders::_1, std::placeholders::_2));
530 
531     ioWaiter_->NotifyAll();
532     ioWaiter_ = newIoWaiter;
533     return true;
534 }
535 
Dump(Dumper & dumper)536 void EventQueue::Dump(Dumper &dumper)
537 {
538     std::lock_guard<std::mutex> lock(queueLock_);
539     if (!usable_.load()) {
540         return;
541     }
542     std::string priority[] = {"Immediate", "High", "Low"};
543     uint32_t total = 0;
544     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
545         uint32_t n = 0;
546         dumper.Dump(dumper.GetTag() + " " + priority[i] + " priority event queue information:" + LINE_SEPARATOR);
547         for (auto it = subEventQueues_[i].queue.begin(); it != subEventQueues_[i].queue.end(); ++it) {
548             ++n;
549             dumper.Dump(dumper.GetTag() + " No." + std::to_string(n) + " : " + (*it)->Dump());
550             ++total;
551         }
552         dumper.Dump(
553             dumper.GetTag() + " Total size of " + priority[i] + " events : " + std::to_string(n) + LINE_SEPARATOR);
554     }
555 
556     dumper.Dump(dumper.GetTag() + " Idle priority event queue information:" + LINE_SEPARATOR);
557     int n = 0;
558     for (auto it = idleEvents_.begin(); it != idleEvents_.end(); ++it) {
559         ++n;
560         dumper.Dump(dumper.GetTag() + " No." + std::to_string(n) + " : " + (*it)->Dump());
561         ++total;
562     }
563     dumper.Dump(dumper.GetTag() + " Total size of Idle events : " + std::to_string(n) + LINE_SEPARATOR);
564 
565     dumper.Dump(dumper.GetTag() + " Total event size : " + std::to_string(total) + LINE_SEPARATOR);
566 }
567 
DumpQueueInfo(std::string & queueInfo)568 void EventQueue::DumpQueueInfo(std::string& queueInfo)
569 {
570     std::lock_guard<std::mutex> lock(queueLock_);
571     if (!usable_.load()) {
572         return;
573     }
574     std::string priority[] = {"Immediate", "High", "Low"};
575     uint32_t total = 0;
576     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
577         uint32_t n = 0;
578         queueInfo +=  "            " + priority[i] + " priority event queue:" + LINE_SEPARATOR;
579         for (auto it = subEventQueues_[i].queue.begin(); it != subEventQueues_[i].queue.end(); ++it) {
580             ++n;
581             queueInfo +=  "            No." + std::to_string(n) + " : " + (*it)->Dump();
582             ++total;
583         }
584         queueInfo +=  "              Total size of " + priority[i] + " events : " + std::to_string(n) + LINE_SEPARATOR;
585     }
586 
587     queueInfo += "            Idle priority event queue:" + LINE_SEPARATOR;
588 
589     int n = 0;
590     for (auto it = idleEvents_.begin(); it != idleEvents_.end(); ++it) {
591         ++n;
592         queueInfo += "            No." + std::to_string(n) + " : " + (*it)->Dump();
593         ++total;
594     }
595     queueInfo += "              Total size of Idle events : " + std::to_string(n) + LINE_SEPARATOR;
596 
597     queueInfo += "            Total event size : " + std::to_string(total);
598 }
599 
IsIdle()600 bool EventQueue::IsIdle()
601 {
602     return isIdle_;
603 }
604 
IsQueueEmpty()605 bool EventQueue::IsQueueEmpty()
606 {
607     std::lock_guard<std::mutex> lock(queueLock_);
608     if (!usable_.load()) {
609         return false;
610     }
611     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
612         uint32_t queueSize = subEventQueues_[i].queue.size();
613         if (queueSize != 0) {
614             return false;
615         }
616     }
617 
618     return idleEvents_.size() == 0;
619 }
620 }  // namespace AppExecFwk
621 }  // namespace OHOS
622