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