1 /* 2 * Copyright (c) 2021-2024 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 #ifndef HIVIEW_BASE_EVENT_LOOP_H 16 #define HIVIEW_BASE_EVENT_LOOP_H 17 #include <atomic> 18 #include <future> 19 #include <map> 20 #include <memory> 21 22 #include <sys/types.h> 23 24 #include "defines.h" 25 #include "event.h" 26 #include "event_priority_queue.h" 27 28 #if defined(__HIVIEW_OHOS__) 29 #include "unique_fd.h" 30 #ifdef USE_POLL 31 #include <poll.h> 32 #endif 33 #elif defined(_WIN32) 34 #include <Windows.h> 35 #include <winnt.h> 36 #endif 37 38 namespace OHOS { 39 namespace HiviewDFX { 40 constexpr int LOOP_WAKEUP_HANDLE_INDEX = 0; 41 constexpr int MAX_EVENT_SIZE = 16; 42 constexpr int MAX_HANDLE_ARRAY_SIZE = 1; 43 constexpr int MAX_WATCHED_FDS = 64; 44 45 enum LoopEventType { 46 LOOP_EVENT_TASK, 47 LOOP_PACKAGED_TASK, 48 }; 49 struct LoopEvent { 50 bool isRepeat = false; 51 uint8_t taskType = 0; 52 uint64_t seq = 0; 53 uint64_t interval = 0; 54 uint64_t enqueueTime = 0; 55 uint64_t targetTime = 0; 56 std::shared_ptr<Event> event = nullptr; 57 std::shared_ptr<EventHandler> handler = nullptr; 58 Task task = nullptr; 59 std::shared_ptr<std::packaged_task<bool()>> packagedTask = nullptr; 60 CreateLoopEventLoopEvent61 static LoopEvent CreateLoopEvent(uint64_t now) 62 { 63 LoopEvent event; 64 event.isRepeat = false; 65 event.taskType = LOOP_EVENT_TASK; 66 event.seq = now; 67 event.interval = 0; 68 event.enqueueTime = now; 69 event.targetTime = now; 70 event.event = nullptr; 71 event.handler = nullptr; 72 event.task = nullptr; 73 event.packagedTask = nullptr; 74 return event; 75 } 76 77 bool operator<(const LoopEvent &obj) const 78 { 79 // as we use std::priority_queue, the event with smaller target time will be in the top of the queue 80 return (this->targetTime > obj.targetTime); 81 } 82 }; 83 84 class FileDescriptorEventCallback { 85 public: ~FileDescriptorEventCallback()86 virtual ~FileDescriptorEventCallback(){}; 87 #if defined(__HIVIEW_OHOS__) 88 virtual bool OnFileDescriptorEvent(int fd, int Type) = 0; 89 virtual int32_t GetPollFd() = 0; 90 virtual int32_t GetPollType() = 0; 91 #elif defined(_WIN32) 92 virtual bool OnHandleEvent(std::string fileName, DWORD action) = 0; 93 #endif 94 }; 95 class DllExport EventLoop { 96 public: 97 explicit EventLoop(const std::string &name); 98 virtual ~EventLoop(); 99 void StartLoop(bool createNewThread = true); 100 void StopLoop(); 101 102 // poll event from file descriptor source 103 // the interfaces may change on windows platform 104 bool AddFileDescriptorEventCallback(const std::string &name, std::shared_ptr<FileDescriptorEventCallback> source); 105 bool RemoveFileDescriptorEventCallback(const std::string &name); 106 107 // process event immediately 108 uint64_t AddEvent(std::shared_ptr<EventHandler> handler, std::shared_ptr<Event> event, const Task task = nullptr); 109 std::future<bool> AddEventForResult(std::shared_ptr<EventHandler> handler, std::shared_ptr<Event> event); 110 111 // process delayed event 112 // interval in seconds 113 virtual uint64_t AddTimerEvent(std::shared_ptr<EventHandler> handler, std::shared_ptr<Event> event, 114 const Task &task, uint64_t interval, bool repeat); 115 bool RemoveEvent(uint64_t seq); 116 117 std::string GetRawName() const; 118 GetName()119 const std::string &GetName() const 120 { 121 return name_; 122 }; 123 IsRunning()124 bool IsRunning() const 125 { 126 return isRunning_; 127 }; 128 129 private: 130 // call from audit module GetHandlerInfo(const LoopEvent &)131 std::string GetHandlerInfo(const LoopEvent &) 132 { 133 return ""; 134 }; 135 136 bool InitEventQueueNotifier(); 137 void InitThreadName(); 138 void Run(); 139 void WakeUp(); 140 uint64_t ProcessQueuedEvent(); 141 void WaitNextEvent(uint64_t leftTimeMill); 142 bool FetchNextEvent(uint64_t now, uint64_t& leftTimeNanosecond, LoopEvent& event); 143 void ProcessEvent(LoopEvent &event); 144 void ReInsertPeriodicEvent(uint64_t now, LoopEvent &event); 145 void ResetTimerIfNeedLocked(); 146 uint64_t NanoSecondSinceSystemStart(); 147 volatile bool isWaken_ = false; 148 volatile bool needQuit_ = false; 149 volatile bool isRunning_ = false; 150 std::string name_; 151 EventPriorityQueue<LoopEvent> pendingEvents_; 152 std::unique_ptr<std::thread> thread_; 153 std::mutex queueMutex_; 154 #if defined(__HIVIEW_OHOS__) 155 #ifdef USE_POLL 156 void ModifyFdStatus(); 157 void PollNextEvent(uint64_t timeout); 158 volatile bool modifyFdStatus_ = false; 159 int32_t eventQueueFd_[2] = {-1, -1}; // 2:event queue fd size 160 int32_t watchedFdSize_ = 1; 161 struct pollfd watchFds_[MAX_WATCHED_FDS]; 162 #else 163 UniqueFd pendingEventQueueFd_; 164 UniqueFd sharedPollingFd_; 165 #endif 166 std::map<int32_t, std::shared_ptr<FileDescriptorEventCallback>> eventSourceMap_; 167 std::map<std::string, int32_t> eventSourceNameMap_; 168 #elif defined(_WIN32) 169 HANDLE watchHandleList_[MAX_HANDLE_ARRAY_SIZE] = {NULL}; 170 #endif 171 uint64_t nextWakeupTime_; 172 std::atomic<LoopEvent *> currentProcessingEvent_; 173 }; 174 } // namespace HiviewDFX 175 } // namespace OHOS 176 #endif // HIVIEW_BASE_EVENT_LOOP_H