1 /* 2 * Copyright (c) 2021-2023 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 #ifndef BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H 17 #define BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H 18 19 #include <array> 20 #include <atomic> 21 #include <functional> 22 #include <list> 23 #include <map> 24 #include <mutex> 25 26 #include "inner_event.h" 27 #include "event_handler_errors.h" 28 #include "file_descriptor_listener.h" 29 #include "dumper.h" 30 31 namespace OHOS { 32 namespace AppExecFwk { 33 class IoWaiter; 34 class EventHandler; 35 class DeamonIoWaiter; 36 struct PendingTaskInfo; 37 38 enum class EventInsertType: uint32_t { 39 // Insert event at end 40 AT_END = 0, 41 // Insert event at front 42 AT_FRONT 43 }; 44 45 enum class Observer { 46 ARKTS_GC, 47 }; 48 49 enum class EventRunnerStage { 50 // enter loop 51 STAGE_ENTRY_RUNNER = 1<<0, 52 // exit loop 53 STAGE_EXIT_RUNNER = 1<<1, 54 // waiting 55 STAGE_BEFORE_WAITING = 1<<2, 56 // recover form sleeping 57 STAGE_AFTER_WAITING = 1<<3, 58 // insert vip task 59 STAGE_VIP_EXISTED = 1<<4, 60 // current queue not exists vip task 61 STAGE_VIP_NONE = 1<<5, 62 // invaild key 63 STAGE_INVAILD = 0, 64 }; 65 66 struct StageInfo { 67 // STAGE_BEFORE_WAITING, timesteap 68 int64_t timestamp; 69 // STAGE_BEFORE_WAITING, milliseconds 70 int32_t sleepTime; 71 // STAGE_AFTER_WAITING 72 int reason; 73 }; 74 75 using EventRunnerObserverCallBack = std::function<int(EventRunnerStage stage, const StageInfo* info)>; 76 77 struct EventRunnerObserver { 78 Observer observer; 79 uint32_t stages; 80 EventRunnerObserverCallBack notifyCb; ClearObserverEventRunnerObserver81 void ClearObserver() 82 { 83 stages = static_cast<uint32_t>(EventRunnerStage::STAGE_INVAILD); 84 notifyCb = nullptr; 85 } 86 }; 87 88 struct ObserverTrace { 89 std::string source; 90 std::string stage; ObserverTraceObserverTrace91 ObserverTrace() {}; ObserverTraceObserverTrace92 ObserverTrace(std::string currentSource, std::string currentStage) 93 : source(currentSource), stage(currentStage) {} getTraceInfoObserverTrace94 std::string getTraceInfo() 95 { 96 std::string traceInfo; 97 traceInfo.append("Et-obs:"); 98 if (stage.empty()) { 99 traceInfo.append(" "); 100 } else { 101 traceInfo.append(stage); 102 } 103 traceInfo.append(","); 104 if (!source.empty()) { 105 traceInfo.append(source); 106 } 107 return traceInfo; 108 } 109 }; 110 111 class EventQueue { 112 public: 113 // Priority for the events 114 enum class Priority : uint32_t { 115 // The highest priority queue, should be distributed until the tasks in the queue are completed. 116 VIP = 0, 117 // Event that should be distributed at once if possible. 118 IMMEDIATE, 119 // High priority event, sorted by handle time, should be distributed before low priority event. 120 HIGH, 121 // Normal event, sorted by handle time. 122 LOW, 123 // Event that should be distributed only if no other event right now. 124 IDLE, 125 }; 126 127 EventQueue(); 128 explicit EventQueue(const std::shared_ptr<IoWaiter> &ioWaiter); 129 virtual ~EventQueue(); 130 DISALLOW_COPY_AND_MOVE(EventQueue); 131 132 /** 133 * Insert an event into event queue with different priority. 134 * The events will be sorted by handle time. 135 * 136 * @param event Event instance which should be added into event queue. 137 * @param Priority Priority of the event 138 * @param insertType The type of insertint event to queue 139 * 140 * @see #Priority 141 */ 142 virtual bool Insert(InnerEvent::Pointer &event, Priority priority = Priority::LOW, 143 EventInsertType insertType = EventInsertType::AT_END, bool noBarrier = false) = 0; 144 145 /** 146 * Remove events if its owner is invalid, for base queue. 147 */ RemoveOrphan()148 virtual void RemoveOrphan() {}; 149 150 /** 151 * Remove events if its owner is invalid, for ffrt queue. 152 */ RemoveOrphanByHandlerId(const std::string & handlerId)153 virtual void RemoveOrphanByHandlerId(const std::string& handlerId) { (void)handlerId; }; 154 155 /** 156 * Remove all events. 157 */ 158 virtual void RemoveAll() = 0; 159 160 /** 161 * Remove events with specified requirements. 162 * 163 * @param owner Owner of the event which is point to an instance of 'EventHandler'. 164 */ 165 virtual void Remove(const std::shared_ptr<EventHandler> &owner) = 0; 166 167 /** 168 * Remove events with specified requirements. 169 * 170 * @param owner Owner of the event which is point to an instance of 'EventHandler'. 171 * @param innerEventId Remove events by event id. 172 */ 173 virtual void Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId) = 0; 174 175 /** 176 * Remove events with specified requirements. 177 * 178 * @param owner Owner of the event which is point to an instance of 'EventHandler'. 179 * @param innerEventId Remove events by event id. 180 * @param param Remove events by value of param. 181 */ 182 virtual void Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId, int64_t param) = 0; 183 184 /** 185 * Remove events with specified requirements. 186 * 187 * @param owner Owner of the event which is point to an instance of 'EventHandler'. 188 * @param name Remove events by name of the task. 189 */ 190 virtual bool Remove(const std::shared_ptr<EventHandler> &owner, const std::string &name) = 0; 191 192 /** 193 * Add file descriptor listener for a file descriptor. 194 * 195 * @param fileDescriptor File descriptor. 196 * @param events Events from file descriptor, such as input, output, error 197 * @param listener Listener callback. 198 * @return Return 'ERR_OK' on success. 199 */ 200 virtual ErrCode AddFileDescriptorListener(int32_t fileDescriptor, uint32_t events, 201 const std::shared_ptr<FileDescriptorListener> &listener, const std::string &taskName, 202 Priority priority = Priority::HIGH) = 0; 203 204 /** 205 * Remove all file descriptor listeners for a specified owner. 206 * 207 * @param owner Owner of the event which is point to an instance of 'FileDescriptorListener'. 208 */ 209 virtual void RemoveFileDescriptorListener(const std::shared_ptr<EventHandler> &owner) = 0; 210 211 /** 212 * Remove file descriptor listener for a file descriptor. 213 * 214 * @param fileDescriptor File descriptor. 215 */ 216 virtual void RemoveFileDescriptorListener(int32_t fileDescriptor) = 0; 217 218 /** 219 * Prepare event queue, before calling {@link #GetEvent}. 220 * If {@link #Finish} is called, prepare event queue again, before calling {@link #GetEvent}. 221 */ 222 virtual void Prepare() = 0; 223 224 /** 225 * Exit from blocking in {@link #GetEvent}, and mark the event queue finished. 226 * After calling {@link #Finish}, {@link #GetEvent} never returns any event, until {@link #Prepare} is called. 227 */ 228 virtual void Finish() = 0; 229 230 /** 231 * Get event from event queue one by one. 232 * Before calling this method, developers should call {@link #Prepare} first. 233 * If none should be handled right now, the thread will be blocked in this method. 234 * Call {@link #Finish} to exit from blocking. 235 * 236 * @return Returns nullptr if event queue is not prepared yet, or {@link #Finish} is called. 237 * Otherwise returns event instance. 238 */ 239 virtual InnerEvent::Pointer GetEvent(); 240 241 /** 242 * Get expired event from event queue one by one. 243 * Before calling this method, developers should call {@link #Prepare} first. 244 * 245 * @param nextExpiredTime Output the expired time for the next event. 246 * @return Returns nullptr if none in event queue is expired. 247 * Otherwise returns event instance. 248 */ 249 virtual InnerEvent::Pointer GetExpiredEvent(InnerEvent::TimePoint &nextExpiredTime); 250 251 /** 252 * Prints out the internal information about an object in the specified format, 253 * helping you diagnose internal errors of the object. 254 * 255 * @param dumper The Dumper object you have implemented to process the output internal information. 256 */ 257 virtual void Dump(Dumper &dumper) = 0; 258 259 /** 260 * Print out the internal information about an object in the specified format, 261 * helping you diagnose internal errors of the object. 262 * 263 * @param queueInfo queue Info. 264 */ 265 virtual void DumpQueueInfo(std::string& queueInfo) = 0; 266 267 /** 268 * Checks whether the current EventHandler is idle. 269 * 270 * @return Returns true if all events have been processed; returns false otherwise. 271 */ 272 virtual bool IsIdle() = 0; 273 274 /** 275 * Check whether this event queue is empty. 276 * 277 * @return If queue is empty return true otherwise return false. 278 */ 279 virtual bool IsQueueEmpty() = 0; 280 281 /** 282 * Check whether an event with the given ID can be found among the events that have been sent but not processed. 283 * 284 * @param owner Owner of the event which is point to an instance of 'EventHandler'. 285 * @param innerEventId The id of the event. 286 */ 287 virtual bool HasInnerEvent(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId) = 0; 288 289 /** 290 * Check whether an event carrying the given param can be found among the events that have been sent but not 291 * processed. 292 * 293 * @param owner The owner of the event which is point to an instance of 'EventHandler'. 294 * @param param The basic parameter of the event. 295 */ 296 virtual bool HasInnerEvent(const std::shared_ptr<EventHandler> &owner, int64_t param) = 0; 297 PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer & event)298 virtual void PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer &event) { (void)event; } 299 PushHistoryQueueAfterDistribute()300 virtual void PushHistoryQueueAfterDistribute() {} 301 302 virtual bool HasPreferEvent(int basePrio) = 0; 303 304 virtual std::string DumpCurrentQueueSize() = 0; 305 306 /** 307 * Check whether there are currenty file descriptors is need to be processed. 308 */ 309 void CheckFileDescriptorEvent(); 310 311 /** 312 * Set waiter mode, true for deamon io waiter 313 */ SetIoWaiter(bool useDeamonIoWaiter)314 void SetIoWaiter(bool useDeamonIoWaiter) 315 { 316 useDeamonIoWaiter_ = useDeamonIoWaiter; 317 } 318 319 /** 320 * Get ffrt queue handler type, only for ffrt thread mode. 321 */ GetFfrtQueue()322 virtual void* GetFfrtQueue() { return nullptr; } 323 324 /** 325 * Insert task to ffrt queue, and wait to handled, only for ffrt thread mode. 326 */ 327 virtual bool InsertSyncEvent(InnerEvent::Pointer &event, Priority priority = Priority::LOW, 328 EventInsertType insertType = EventInsertType::AT_END) 329 { 330 (void)event; 331 (void)priority; 332 (void)insertType; 333 return true; 334 } 335 336 /** 337 * Get pending task info 338 */ 339 virtual PendingTaskInfo QueryPendingTaskInfo(int32_t fileDescriptor) = 0; 340 /** 341 * add observer 342 * 343 * @param observer runner observer. 344 * @param stages The stages of observer 345 * @param callback observer callback. 346 */ AddObserver(Observer observer,uint32_t stages,EventRunnerObserverCallBack callback)347 void AddObserver(Observer observer, uint32_t stages, EventRunnerObserverCallBack callback) 348 { 349 observer_.observer = observer; 350 observer_.notifyCb = callback; 351 observer_.stages = stages; 352 } 353 354 /** 355 * Cancel And Wait 356 */ 357 virtual void CancelAndWait() = 0; 358 359 /** 360 * notify GC Observer vip events finished 361 */ 362 virtual void NotifyObserverVipDone(const InnerEvent::Pointer &event); 363 364 /** 365 * Get the first event handle time in the prioritized task queue. 366 * 367 * @param priority The specified priority. 368 */ 369 virtual inline uint64_t GetQueueFirstEventHandleTime(int32_t priority) = 0; 370 371 /** 372 * Set the lazy mode for AppVsync 373 */ 374 void SetVsyncLazyMode(bool isLazy); 375 376 /** 377 * Set the waiter of AppVsync 378 */ 379 void SetVsyncWaiter(bool isDaemon); 380 381 /** 382 * the vsync task is comming. 383 */ DispatchVsyncTaskNotify()384 inline void DispatchVsyncTaskNotify() 385 { 386 ++sumOfPendingVsync_; 387 if (epollTimePoint_ < InnerEvent::Clock::now()) { 388 needEpoll_.store(true); 389 } 390 } 391 392 /** 393 * the vsync task be handled. 394 */ HandleVsyncTaskNotify()395 inline void HandleVsyncTaskNotify() 396 { 397 --sumOfPendingVsync_; 398 } 399 400 /** 401 * set the barrier mode. 402 */ SetBarrierMode(bool isBarrierMode)403 inline void SetBarrierMode(bool isBarrierMode) 404 { 405 isBarrierMode_ = isBarrierMode; 406 enterBarrierTime_ = !isBarrierMode? UINT64_MAX : 407 static_cast<uint64_t>(InnerEvent::Clock::now().time_since_epoch().count()); 408 } 409 410 /** 411 * get the barrier mode. 412 */ IsBarrierMode()413 inline bool IsBarrierMode() 414 { 415 return isBarrierMode_; 416 } 417 418 protected: 419 void RemoveInvalidFileDescriptor(); 420 421 /** 422 * Add file descriptor base. 423 * 424 * @param fileDescriptor File descriptor. 425 * @param events Events from file descriptor, such as input, output, error 426 * @param listener Listener callback. 427 * @param taskName task name. 428 * @param Priority Priority of the event. 429 * @return Return result ErrCode. 430 */ 431 ErrCode AddFileDescriptorListenerBase(int32_t fileDescriptor, uint32_t events, 432 const std::shared_ptr<FileDescriptorListener> &listener, const std::string &taskName, 433 Priority priority); 434 435 /** 436 * Add file descriptor by fd. 437 * 438 * @param fileDescriptor File descriptor. 439 * @param events Events from file descriptor, such as input, output, error 440 * @param taskName task name. 441 * @param listener Listener callback. 442 * @param Priority Priority of the event. 443 * @return Return result boolean. 444 */ 445 bool AddFileDescriptorByFd(int32_t fileDescriptor, uint32_t events, const std::string &taskName, 446 const std::shared_ptr<FileDescriptorListener>& listener, EventQueue::Priority priority); 447 448 bool EnsureIoWaiterLocked(const std::shared_ptr<FileDescriptorListener>& listener); 449 450 /** 451 * handle file descriptor event. 452 * 453 * @param fileDescriptor File descriptor. 454 * @param events Events from file descriptor, such as input, output, error 455 * @param name task name. 456 * @param Priority Priority of the event. 457 */ 458 void HandleFileDescriptorEvent(int32_t fileDescriptor, uint32_t events, const std::string &name, 459 Priority priority); 460 461 /** 462 * remove listener by owner. 463 * 464 * @param owner current eventhandler. 465 */ 466 void RemoveListenerByOwner(const std::shared_ptr<EventHandler> &owner); 467 468 /** 469 * remove listener by fd. 470 * 471 * @param fileDescriptor fd. 472 */ 473 void RemoveListenerByFd(int32_t fileDescriptor); 474 475 void PrepareBase(); 476 477 void FinishBase(); 478 479 void WaitUntilLocked(const InnerEvent::TimePoint &when, std::unique_lock<std::mutex> &lock); 480 std::mutex queueLock_; 481 482 std::atomic_bool usable_ {true}; 483 484 bool isIdle_ {true}; 485 486 // Mark if the event queue is finished. 487 bool finished_ {true}; 488 489 // IO waiter used to block if no events while calling 'GetEvent'. 490 std::shared_ptr<IoWaiter> ioWaiter_; 491 492 // select different epoll 493 bool useDeamonIoWaiter_ = false; 494 495 // File descriptor listeners to handle IO events. 496 std::map<int32_t, std::shared_ptr<FileDescriptorListener>> listeners_; 497 498 EventRunnerObserver observer_ = {.stages = static_cast<uint32_t>(EventRunnerStage::STAGE_INVAILD), 499 .notifyCb = nullptr}; 500 501 std::atomic_int8_t sumOfPendingVsync_ = 0; 502 std::atomic_bool needEpoll_ = true; 503 std::atomic_bool isLazyMode_ = true; 504 bool isBarrierMode_ = false; 505 bool isVsyncOnDaemon_ = true; 506 Priority vsyncPriority_ = Priority::VIP; 507 InnerEvent::TimePoint epollTimePoint_; 508 uint64_t enterBarrierTime_ = UINT64_MAX; 509 }; 510 } // namespace AppExecFwk 511 } // namespace OHOS 512 513 #endif // #ifndef BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H 514