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 #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 <list> 22 #include <map> 23 #include <mutex> 24 25 #include "inner_event.h" 26 #include "event_handler_errors.h" 27 #include "file_descriptor_listener.h" 28 #include "dumper.h" 29 #include "logger.h" 30 31 namespace OHOS { 32 namespace AppExecFwk { 33 class IoWaiter; 34 35 class EventQueue final { 36 public: 37 // Priority for the events 38 enum class Priority : uint32_t { 39 // The highest priority queue, should be distributed until the tasks in the queue are completed. 40 VIP = 0, 41 // Event that should be distributed at once if possible. 42 IMMEDIATE, 43 // High priority event, sorted by handle time, should be distributed before low priority event. 44 HIGH, 45 // Normal event, sorted by handle time. 46 LOW, 47 // Event that should be distributed only if no other event right now. 48 IDLE, 49 }; 50 51 EventQueue(); 52 explicit EventQueue(const std::shared_ptr<IoWaiter> &ioWaiter); 53 ~EventQueue(); 54 DISALLOW_COPY_AND_MOVE(EventQueue); 55 56 /** 57 * Insert an event into event queue with different priority. 58 * The events will be sorted by handle time. 59 * 60 * @param event Event instance which should be added into event queue. 61 * @param Priority Priority of the event 62 * 63 * @see #Priority 64 */ 65 void Insert(InnerEvent::Pointer &event, Priority priority = Priority::LOW); 66 67 /** 68 * Remove events if its owner is invalid. 69 */ 70 void RemoveOrphan(); 71 72 /** 73 * Remove events with specified requirements. 74 * 75 * @param owner Owner of the event which is point to an instance of 'EventHandler'. 76 */ 77 void Remove(const std::shared_ptr<EventHandler> &owner); 78 79 /** 80 * Remove events with specified requirements. 81 * 82 * @param owner Owner of the event which is point to an instance of 'EventHandler'. 83 * @param innerEventId Remove events by event id. 84 */ 85 void Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId); 86 87 /** 88 * Remove events with specified requirements. 89 * 90 * @param owner Owner of the event which is point to an instance of 'EventHandler'. 91 * @param innerEventId Remove events by event id. 92 * @param param Remove events by value of param. 93 */ 94 void Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId, int64_t param); 95 96 /** 97 * Remove events with specified requirements. 98 * 99 * @param owner Owner of the event which is point to an instance of 'EventHandler'. 100 * @param name Remove events by name of the task. 101 */ 102 void Remove(const std::shared_ptr<EventHandler> &owner, const std::string &name); 103 104 /** 105 * Add file descriptor listener for a file descriptor. 106 * 107 * @param fileDescriptor File descriptor. 108 * @param events Events from file descriptor, such as input, output, error 109 * @param listener Listener callback. 110 * @return Return 'ERR_OK' on success. 111 */ 112 ErrCode AddFileDescriptorListener( 113 int32_t fileDescriptor, uint32_t events, const std::shared_ptr<FileDescriptorListener> &listener); 114 115 /** 116 * Remove all file descriptor listeners for a specified owner. 117 * 118 * @param owner Owner of the event which is point to an instance of 'FileDescriptorListener'. 119 */ 120 void RemoveFileDescriptorListener(const std::shared_ptr<EventHandler> &owner); 121 122 /** 123 * Remove file descriptor listener for a file descriptor. 124 * 125 * @param fileDescriptor File descriptor. 126 */ 127 void RemoveFileDescriptorListener(int32_t fileDescriptor); 128 129 /** 130 * Prepare event queue, before calling {@link #GetEvent}. 131 * If {@link #Finish} is called, prepare event queue again, before calling {@link #GetEvent}. 132 */ 133 void Prepare(); 134 135 /** 136 * Exit from blocking in {@link #GetEvent}, and mark the event queue finished. 137 * After calling {@link #Finish}, {@link #GetEvent} never returns any event, until {@link #Prepare} is called. 138 */ 139 void Finish(); 140 141 /** 142 * Get event from event queue one by one. 143 * Before calling this method, developers should call {@link #Prepare} first. 144 * If none should be handled right now, the thread will be blocked in this method. 145 * Call {@link #Finish} to exit from blocking. 146 * 147 * @return Returns nullptr if event queue is not prepared yet, or {@link #Finish} is called. 148 * Otherwise returns event instance. 149 */ 150 InnerEvent::Pointer GetEvent(); 151 152 /** 153 * Get expired event from event queue one by one. 154 * Before calling this method, developers should call {@link #Prepare} first. 155 * 156 * @param nextExpiredTime Output the expired time for the next event. 157 * @return Returns nullptr if none in event queue is expired. 158 * Otherwise returns event instance. 159 */ 160 InnerEvent::Pointer GetExpiredEvent(InnerEvent::TimePoint &nextExpiredTime); 161 162 /** 163 * Prints out the internal information about an object in the specified format, 164 * helping you diagnose internal errors of the object. 165 * 166 * @param dumpr The Dumper object you have implemented to process the output internal information. 167 */ 168 void Dump(Dumper &dumper); 169 170 /** 171 * Print out the internal information about an object in the specified format, 172 * helping you diagnose internal errors of the object. 173 * 174 * @param queueInfo queue Info. 175 */ 176 void DumpQueueInfo(std::string& queueInfo); 177 178 /** 179 * Checks whether the current EventHandler is idle. 180 * 181 * @return Returns true if all events have been processed; returns false otherwise. 182 */ 183 bool IsIdle(); 184 185 /** 186 * Check whether this event queue is empty. 187 * 188 * @return If queue is empty return true otherwise return false. 189 */ 190 bool IsQueueEmpty(); 191 192 /** 193 * Check whether an event with the given ID can be found among the events that have been sent but not processed. 194 * 195 * @param owner Owner of the event which is point to an instance of 'EventHandler'. 196 * @param innerEventId The id of the event. 197 */ 198 bool HasInnerEvent(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId); 199 200 /** 201 * Check whether an event carrying the given param can be found among the events that have been sent but not 202 * processed. 203 * 204 * @param owner The owner of the event which is point to an instance of 'EventHandler'. 205 * @param param The basic parameter of the event. 206 */ 207 bool HasInnerEvent(const std::shared_ptr<EventHandler> &owner, int64_t param); 208 209 private: 210 using RemoveFilter = std::function<bool(const InnerEvent::Pointer &)>; 211 using HasFilter = std::function<bool(const InnerEvent::Pointer &)>; 212 213 /* 214 * To avoid starvation of lower priority event queue, give a chance to process lower priority events, 215 * after continuous processing several higher priority events. 216 */ 217 static const uint32_t DEFAULT_MAX_HANDLED_EVENT_COUNT = 5; 218 219 // Sub event queues for IMMEDIATE, HIGH and LOW priority. So use value of IDLE as size. 220 static const uint32_t SUB_EVENT_QUEUE_NUM = static_cast<uint32_t>(Priority::IDLE); 221 222 struct SubEventQueue { 223 std::list<InnerEvent::Pointer> queue; 224 uint32_t handledEventsCount{0}; 225 uint32_t maxHandledEventsCount{DEFAULT_MAX_HANDLED_EVENT_COUNT}; 226 }; 227 228 void Remove(const RemoveFilter &filter); 229 bool HasInnerEvent(const HasFilter &filter); 230 InnerEvent::Pointer PickEventLocked(const InnerEvent::TimePoint &now, InnerEvent::TimePoint &nextWakeUpTime); 231 InnerEvent::Pointer GetExpiredEventLocked(InnerEvent::TimePoint &nextExpiredTime); 232 void WaitUntilLocked(const InnerEvent::TimePoint &when, std::unique_lock<std::mutex> &lock); 233 void HandleFileDescriptorEvent(int32_t fileDescriptor, uint32_t events); 234 bool EnsureIoWaiterSupportListerningFileDescriptorLocked(); 235 236 std::mutex queueLock_; 237 238 std::atomic_bool usable_ {true}; 239 240 // Sub event queues for different priority. 241 std::array<SubEventQueue, SUB_EVENT_QUEUE_NUM> subEventQueues_; 242 243 // Event queue for IDLE events. 244 std::list<InnerEvent::Pointer> idleEvents_; 245 246 // Next wake up time when block in 'GetEvent'. 247 InnerEvent::TimePoint wakeUpTime_ { InnerEvent::TimePoint::max() }; 248 249 // Mark if in idle mode, and record the start time of idle. 250 InnerEvent::TimePoint idleTimeStamp_ { InnerEvent::Clock::now() }; 251 252 bool isIdle_ {true}; 253 254 // Mark if the event queue is finished. 255 bool finished_ {true}; 256 257 // IO waiter used to block if no events while calling 'GetEvent'. 258 std::shared_ptr<IoWaiter> ioWaiter_; 259 260 // File descriptor listeners to handle IO events. 261 std::map<int32_t, std::shared_ptr<FileDescriptorListener>> listeners_; 262 }; 263 } // namespace AppExecFwk 264 } // namespace OHOS 265 266 #endif // #ifndef BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H 267