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