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