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