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