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