1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef __FDEVENT_H 18 #define __FDEVENT_H 19 20 #include <stddef.h> 21 #include <stdint.h> 22 23 #include <atomic> 24 #include <chrono> 25 #include <deque> 26 #include <functional> 27 #include <map> 28 #include <mutex> 29 #include <optional> 30 #include <set> 31 #include <variant> 32 33 #include <android-base/thread_annotations.h> 34 35 #include "adb_unique_fd.h" 36 37 // Events that may be observed 38 #define FDE_READ 0x0001 39 #define FDE_WRITE 0x0002 40 #define FDE_ERROR 0x0004 41 #define FDE_TIMEOUT 0x0008 42 43 struct fdevent; 44 45 typedef void (*fd_func)(int fd, unsigned events, void *userdata); 46 typedef void (*fd_func2)(struct fdevent* fde, unsigned events, void* userdata); 47 48 void invoke_fde(struct fdevent* fde, unsigned events); 49 std::string dump_fde(const fdevent* fde); 50 51 struct fdevent_event { 52 fdevent* fde; 53 unsigned events; fdevent_eventfdevent_event54 fdevent_event(fdevent* pfde, unsigned ev) : fde(pfde), events(ev) {} 55 }; 56 57 struct fdevent final { 58 uint64_t id; 59 60 unique_fd fd; 61 62 uint16_t state = 0; 63 std::optional<std::chrono::milliseconds> timeout; 64 std::chrono::steady_clock::time_point last_active; 65 66 std::variant<fd_func, fd_func2> func; 67 void* arg = nullptr; 68 }; 69 70 struct fdevent_context { 71 public: 72 virtual ~fdevent_context() = default; 73 74 // Allocate and initialize a new fdevent object. 75 fdevent* Create(unique_fd fd, std::variant<fd_func, fd_func2> func, void* arg); 76 77 // Deallocate an fdevent object, returning the file descriptor that was owned by it. 78 // Note that this calls Set, which is a virtual method, so destructors that call this must be 79 // final. 80 unique_fd Destroy(fdevent* fde); 81 82 protected: 83 virtual void Register(fdevent*) = 0; 84 virtual void Unregister(fdevent*) = 0; 85 86 public: 87 // Change which events should cause notifications. 88 virtual void Set(fdevent* fde, unsigned events) = 0; 89 void Add(fdevent* fde, unsigned events); 90 void Del(fdevent* fde, unsigned events); 91 92 // Set a timeout on an fdevent. 93 // If no events are triggered by the timeout, an FDE_TIMEOUT will be generated. 94 // Note timeouts are not defused automatically; if a timeout is set on an fdevent, it will 95 // trigger repeatedly every |timeout| ms. 96 void SetTimeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout); 97 98 protected: 99 std::optional<std::chrono::milliseconds> CalculatePollDuration(); 100 void HandleEvents(const std::vector<fdevent_event>& events); 101 102 private: 103 // Run all pending functions enqueued via Run(). 104 void FlushRunQueue() EXCLUDES(run_queue_mutex_); 105 106 public: 107 // Loop until TerminateLoop is called, handling events. 108 // Implementations should call FlushRunQueue on every iteration, and check the value of 109 // terminate_loop_ to determine whether to stop. 110 virtual void Loop() = 0; 111 112 // Assert that the caller is executing in the context of the execution 113 // thread that invoked Loop(). 114 void CheckLooperThread() const; 115 116 // Queue an operation to be run on the looper thread. 117 void Run(std::function<void()> fn); 118 119 // Test-only functionality: 120 void TerminateLoop(); 121 virtual size_t InstalledCount() = 0; 122 123 protected: 124 // Interrupt the run loop. 125 virtual void Interrupt() = 0; 126 127 std::optional<uint64_t> looper_thread_id_ = std::nullopt; 128 std::atomic<bool> terminate_loop_ = false; 129 130 std::map<int, fdevent> installed_fdevents_; 131 132 private: 133 uint64_t fdevent_id_ = 0; 134 std::mutex run_queue_mutex_; 135 std::deque<std::function<void()>> run_queue_ GUARDED_BY(run_queue_mutex_); 136 137 std::set<fdevent*> fdevent_set_; 138 }; 139 140 // Backwards compatibility shims that forward to the global fdevent_context. 141 fdevent* fdevent_create(int fd, fd_func func, void* arg); 142 fdevent* fdevent_create(int fd, fd_func2 func, void* arg); 143 144 unique_fd fdevent_release(fdevent* fde); 145 void fdevent_destroy(fdevent* fde); 146 147 void fdevent_set(fdevent *fde, unsigned events); 148 void fdevent_add(fdevent *fde, unsigned events); 149 void fdevent_del(fdevent *fde, unsigned events); 150 void fdevent_set_timeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout); 151 void fdevent_loop(); 152 153 // Delegates to the member function that checks for the initialization 154 // of Loop() so that fdevent_context requests can be serially processed 155 // by the global instance robustly. 156 void fdevent_check_looper(); 157 158 // Queue an operation to run on the looper event thread. 159 void fdevent_run_on_looper(std::function<void()> fn); 160 161 // The following functions are used only for tests. 162 void fdevent_terminate_loop(); 163 size_t fdevent_installed_count(); 164 void fdevent_reset(); 165 166 #endif 167