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