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