• 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 #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         if (!p) {
234             return false;
235         }
236         return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId);
237     };
238     return HasInnerEvent(filter);
239 }
240 
HasInnerEvent(const std::shared_ptr<EventHandler> & owner,int64_t param)241 bool EventQueue::HasInnerEvent(const std::shared_ptr<EventHandler> &owner, int64_t param)
242 {
243     if (!owner) {
244         HILOGE("HasInnerEvent: Invalid owner");
245         return false;
246     }
247     auto filter = [&owner, param](const InnerEvent::Pointer &p) {
248         if (!p) {
249             return false;
250         }
251         return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetParam() == param);
252     };
253     return HasInnerEvent(filter);
254 }
255 
HasInnerEvent(const HasFilter & filter)256 bool EventQueue::HasInnerEvent(const HasFilter &filter)
257 {
258     std::lock_guard<std::mutex> lock(queueLock_);
259     if (!usable_.load()) {
260         return false;
261     }
262     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
263         std::list<InnerEvent::Pointer>::iterator iter =
264             std::find_if(subEventQueues_[i].queue.begin(), subEventQueues_[i].queue.end(), filter);
265         if (iter != subEventQueues_[i].queue.end()) {
266             return true;
267         }
268     }
269     std::list<InnerEvent::Pointer>::iterator iter = std::find_if(idleEvents_.begin(), idleEvents_.end(), filter);
270     return iter != idleEvents_.end();
271 }
272 
PickEventLocked(const InnerEvent::TimePoint & now,InnerEvent::TimePoint & nextWakeUpTime)273 InnerEvent::Pointer EventQueue::PickEventLocked(const InnerEvent::TimePoint &now, InnerEvent::TimePoint &nextWakeUpTime)
274 {
275     uint32_t priorityIndex = SUB_EVENT_QUEUE_NUM;
276     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
277         // Check whether any event need to be distributed.
278         if (!CheckEventInListLocked(subEventQueues_[i].queue, now, nextWakeUpTime)) {
279             continue;
280         }
281 
282         // Check whether any event in higher priority need to be distributed.
283         if (priorityIndex < SUB_EVENT_QUEUE_NUM) {
284             SubEventQueue &subQueue = subEventQueues_[priorityIndex];
285             // Check whether enough events in higher priority queue are handled continuously.
286             if (subQueue.handledEventsCount < subQueue.maxHandledEventsCount) {
287                 subQueue.handledEventsCount++;
288                 break;
289             }
290         }
291 
292         // Try to pick event from this queue.
293         priorityIndex = i;
294     }
295 
296     if (priorityIndex >= SUB_EVENT_QUEUE_NUM) {
297         // If not found any event to distribute, return nullptr.
298         return InnerEvent::Pointer(nullptr, nullptr);
299     }
300 
301     // Reset handled event count for sub event queues in higher priority.
302     for (uint32_t i = 0; i < priorityIndex; ++i) {
303         subEventQueues_[i].handledEventsCount = 0;
304     }
305 
306     return PopFrontEventFromListLocked(subEventQueues_[priorityIndex].queue);
307 }
308 
GetExpiredEventLocked(InnerEvent::TimePoint & nextExpiredTime)309 InnerEvent::Pointer EventQueue::GetExpiredEventLocked(InnerEvent::TimePoint &nextExpiredTime)
310 {
311     auto now = InnerEvent::Clock::now();
312     wakeUpTime_ = InnerEvent::TimePoint::max();
313     // Find an event which could be distributed right now.
314     InnerEvent::Pointer event = PickEventLocked(now, wakeUpTime_);
315     if (event) {
316         // Exit idle mode, if found an event to distribute.
317         isIdle_ = false;
318         return event;
319     }
320 
321     // If found nothing, enter idle mode and make a time stamp.
322     if (!isIdle_) {
323         idleTimeStamp_ = now;
324         isIdle_ = true;
325     }
326 
327     if (!idleEvents_.empty()) {
328         const auto &idleEvent = idleEvents_.front();
329 
330         // Return the idle event that has been sent before time stamp and reaches its handle time.
331         if ((idleEvent->GetSendTime() <= idleTimeStamp_) && (idleEvent->GetHandleTime() <= now)) {
332             return PopFrontEventFromListLocked(idleEvents_);
333         }
334     }
335 
336     // Update wake up time.
337     nextExpiredTime = wakeUpTime_;
338     return InnerEvent::Pointer(nullptr, nullptr);
339 }
340 
GetEvent()341 InnerEvent::Pointer EventQueue::GetEvent()
342 {
343     std::unique_lock<std::mutex> lock(queueLock_);
344     while (!finished_) {
345         InnerEvent::TimePoint nextWakeUpTime = InnerEvent::TimePoint::max();
346         InnerEvent::Pointer event = GetExpiredEventLocked(nextWakeUpTime);
347         if (event) {
348             return event;
349         }
350         WaitUntilLocked(nextWakeUpTime, lock);
351     }
352 
353     HILOGD("GetEvent: Break out");
354     return InnerEvent::Pointer(nullptr, nullptr);
355 }
356 
GetExpiredEvent(InnerEvent::TimePoint & nextExpiredTime)357 InnerEvent::Pointer EventQueue::GetExpiredEvent(InnerEvent::TimePoint &nextExpiredTime)
358 {
359     std::unique_lock<std::mutex> lock(queueLock_);
360     return GetExpiredEventLocked(nextExpiredTime);
361 }
362 
AddFileDescriptorListener(int32_t fileDescriptor,uint32_t events,const std::shared_ptr<FileDescriptorListener> & listener)363 ErrCode EventQueue::AddFileDescriptorListener(
364     int32_t fileDescriptor, uint32_t events, const std::shared_ptr<FileDescriptorListener> &listener)
365 {
366     if ((fileDescriptor < 0) || ((events & FILE_DESCRIPTOR_EVENTS_MASK) == 0) || (!listener)) {
367         HILOGE("AddFileDescriptorListener(%{public}d, %{public}u, %{public}s): Invalid parameter",
368             fileDescriptor,
369             events,
370             listener ? "valid" : "null");
371         return EVENT_HANDLER_ERR_INVALID_PARAM;
372     }
373 
374     std::lock_guard<std::mutex> lock(queueLock_);
375     if (!usable_.load()) {
376         return EVENT_HANDLER_ERR_NO_EVENT_RUNNER;
377     }
378     auto it = listeners_.find(fileDescriptor);
379     if (it != listeners_.end()) {
380         HILOGE("AddFileDescriptorListener: File descriptor %{public}d is already in listening", fileDescriptor);
381         return EVENT_HANDLER_ERR_FD_ALREADY;
382     }
383 
384     if (!EnsureIoWaiterSupportListerningFileDescriptorLocked()) {
385         return EVENT_HANDLER_ERR_FD_NOT_SUPPORT;
386     }
387 
388     if (!ioWaiter_->AddFileDescriptor(fileDescriptor, events)) {
389         HILOGE("AddFileDescriptorListener: Failed to add file descriptor into IO waiter");
390         return EVENT_HANDLER_ERR_FD_FAILED;
391     }
392 
393     listeners_.emplace(fileDescriptor, listener);
394     return ERR_OK;
395 }
396 
RemoveFileDescriptorListener(const std::shared_ptr<EventHandler> & owner)397 void EventQueue::RemoveFileDescriptorListener(const std::shared_ptr<EventHandler> &owner)
398 {
399     if (!owner) {
400         HILOGE("RemoveFileDescriptorListener: Invalid owner");
401         return;
402     }
403 
404     auto listenerFilter = [&owner](const std::shared_ptr<FileDescriptorListener> &listener) {
405         if (!listener) {
406             return false;
407         }
408         return listener->GetOwner() == owner;
409     };
410 
411     std::lock_guard<std::mutex> lock(queueLock_);
412     if (!usable_.load()) {
413         return;
414     }
415     RemoveFileDescriptorListenerLocked(listeners_, ioWaiter_, listenerFilter);
416 }
417 
RemoveFileDescriptorListener(int32_t fileDescriptor)418 void EventQueue::RemoveFileDescriptorListener(int32_t fileDescriptor)
419 {
420     if (fileDescriptor < 0) {
421         HILOGE("RemoveFileDescriptorListener(%{public}d): Invalid file descriptor", fileDescriptor);
422         return;
423     }
424 
425     std::lock_guard<std::mutex> lock(queueLock_);
426     if (!usable_.load()) {
427         return;
428     }
429     if (listeners_.erase(fileDescriptor) > 0) {
430         ioWaiter_->RemoveFileDescriptor(fileDescriptor);
431     }
432 }
433 
Prepare()434 void EventQueue::Prepare()
435 {
436     std::lock_guard<std::mutex> lock(queueLock_);
437     if (!usable_.load()) {
438         return;
439     }
440     finished_ = false;
441 }
442 
Finish()443 void EventQueue::Finish()
444 {
445     std::lock_guard<std::mutex> lock(queueLock_);
446     if (!usable_.load()) {
447         return;
448     }
449     finished_ = true;
450     ioWaiter_->NotifyAll();
451 }
452 
WaitUntilLocked(const InnerEvent::TimePoint & when,std::unique_lock<std::mutex> & lock)453 void EventQueue::WaitUntilLocked(const InnerEvent::TimePoint &when, std::unique_lock<std::mutex> &lock)
454 {
455     // Get a temp reference of IO waiter, otherwise it maybe released while waiting.
456     auto ioWaiterHolder = ioWaiter_;
457     if (!ioWaiterHolder->WaitFor(lock, TimePointToTimeOut(when))) {
458         HILOGE("WaitUntilLocked: Failed to call wait, reset IO waiter");
459         ioWaiter_ = std::make_shared<NoneIoWaiter>();
460         listeners_.clear();
461     }
462 }
463 
HandleFileDescriptorEvent(int32_t fileDescriptor,uint32_t events)464 void EventQueue::HandleFileDescriptorEvent(int32_t fileDescriptor, uint32_t events)
465 {
466     std::shared_ptr<FileDescriptorListener> listener;
467 
468     {
469         std::lock_guard<std::mutex> lock(queueLock_);
470         if (!usable_.load()) {
471             return;
472         }
473         auto it = listeners_.find(fileDescriptor);
474         if (it == listeners_.end()) {
475             HILOGW("HandleFileDescriptorEvent: Can not found listener, maybe it is removed");
476             return;
477         }
478 
479         // Hold instance of listener.
480         listener = it->second;
481         if (!listener) {
482             return;
483         }
484     }
485 
486     auto handler = listener->GetOwner();
487     if (!handler) {
488         HILOGW("HandleFileDescriptorEvent: Owner of listener is released");
489         return;
490     }
491 
492     std::weak_ptr<FileDescriptorListener> wp = listener;
493     auto f = [fileDescriptor, events, wp]() {
494         auto listener = wp.lock();
495         if (!listener) {
496             HILOGW("HandleFileDescriptorEvent-Lambda: Listener is released");
497             return;
498         }
499 
500         if ((events & FILE_DESCRIPTOR_INPUT_EVENT) != 0) {
501             listener->OnReadable(fileDescriptor);
502         }
503 
504         if ((events & FILE_DESCRIPTOR_OUTPUT_EVENT) != 0) {
505             listener->OnWritable(fileDescriptor);
506         }
507 
508         if ((events & FILE_DESCRIPTOR_SHUTDOWN_EVENT) != 0) {
509             listener->OnShutdown(fileDescriptor);
510         }
511 
512         if ((events & FILE_DESCRIPTOR_EXCEPTION_EVENT) != 0) {
513             listener->OnException(fileDescriptor);
514         }
515     };
516 
517     // Post a high priority task to handle file descriptor events.
518     handler->PostHighPriorityTask(f);
519 }
520 
EnsureIoWaiterSupportListerningFileDescriptorLocked()521 bool EventQueue::EnsureIoWaiterSupportListerningFileDescriptorLocked()
522 {
523     if (ioWaiter_->SupportListeningFileDescriptor()) {
524         return true;
525     }
526 
527     auto newIoWaiter = std::make_shared<EpollIoWaiter>();
528     if (!newIoWaiter->Init()) {
529         HILOGE("EnsureIoWaiterSupportListerningFileDescriptorLocked: Failed to initialize epoll");
530         return false;
531     }
532 
533     // Set callback to handle events from file descriptors.
534     newIoWaiter->SetFileDescriptorEventCallback(
535         std::bind(&EventQueue::HandleFileDescriptorEvent, this, std::placeholders::_1, std::placeholders::_2));
536 
537     ioWaiter_->NotifyAll();
538     ioWaiter_ = newIoWaiter;
539     return true;
540 }
541 
Dump(Dumper & dumper)542 void EventQueue::Dump(Dumper &dumper)
543 {
544     std::lock_guard<std::mutex> lock(queueLock_);
545     if (!usable_.load()) {
546         return;
547     }
548     std::string priority[] = {"Immediate", "High", "Low"};
549     uint32_t total = 0;
550     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
551         uint32_t n = 0;
552         dumper.Dump(dumper.GetTag() + " " + priority[i] + " priority event queue information:" + LINE_SEPARATOR);
553         for (auto it = subEventQueues_[i].queue.begin(); it != subEventQueues_[i].queue.end(); ++it) {
554             ++n;
555             dumper.Dump(dumper.GetTag() + " No." + std::to_string(n) + " : " + (*it)->Dump());
556             ++total;
557         }
558         dumper.Dump(
559             dumper.GetTag() + " Total size of " + priority[i] + " events : " + std::to_string(n) + LINE_SEPARATOR);
560     }
561 
562     dumper.Dump(dumper.GetTag() + " Idle priority event queue information:" + LINE_SEPARATOR);
563     int n = 0;
564     for (auto it = idleEvents_.begin(); it != idleEvents_.end(); ++it) {
565         ++n;
566         dumper.Dump(dumper.GetTag() + " No." + std::to_string(n) + " : " + (*it)->Dump());
567         ++total;
568     }
569     dumper.Dump(dumper.GetTag() + " Total size of Idle events : " + std::to_string(n) + LINE_SEPARATOR);
570 
571     dumper.Dump(dumper.GetTag() + " Total event size : " + std::to_string(total) + LINE_SEPARATOR);
572 }
573 
DumpQueueInfo(std::string & queueInfo)574 void EventQueue::DumpQueueInfo(std::string& queueInfo)
575 {
576     std::lock_guard<std::mutex> lock(queueLock_);
577     if (!usable_.load()) {
578         return;
579     }
580     std::string priority[] = {"Immediate", "High", "Low"};
581     uint32_t total = 0;
582     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
583         uint32_t n = 0;
584         queueInfo +=  "            " + priority[i] + " priority event queue:" + LINE_SEPARATOR;
585         for (auto it = subEventQueues_[i].queue.begin(); it != subEventQueues_[i].queue.end(); ++it) {
586             ++n;
587             queueInfo +=  "            No." + std::to_string(n) + " : " + (*it)->Dump();
588             ++total;
589         }
590         queueInfo +=  "              Total size of " + priority[i] + " events : " + std::to_string(n) + LINE_SEPARATOR;
591     }
592 
593     queueInfo += "            Idle priority event queue:" + LINE_SEPARATOR;
594 
595     int n = 0;
596     for (auto it = idleEvents_.begin(); it != idleEvents_.end(); ++it) {
597         ++n;
598         queueInfo += "            No." + std::to_string(n) + " : " + (*it)->Dump();
599         ++total;
600     }
601     queueInfo += "              Total size of Idle events : " + std::to_string(n) + LINE_SEPARATOR;
602 
603     queueInfo += "            Total event size : " + std::to_string(total);
604 }
605 
IsIdle()606 bool EventQueue::IsIdle()
607 {
608     return isIdle_;
609 }
610 
IsQueueEmpty()611 bool EventQueue::IsQueueEmpty()
612 {
613     std::lock_guard<std::mutex> lock(queueLock_);
614     if (!usable_.load()) {
615         return false;
616     }
617     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
618         uint32_t queueSize = subEventQueues_[i].queue.size();
619         if (queueSize != 0) {
620             return false;
621         }
622     }
623 
624     return idleEvents_.size() == 0;
625 }
626 }  // namespace AppExecFwk
627 }  // namespace OHOS
628