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; 54 }; 55 56 struct fdevent final { 57 uint64_t id; 58 59 unique_fd fd; 60 61 uint16_t state = 0; 62 std::optional<std::chrono::milliseconds> timeout; 63 std::chrono::steady_clock::time_point last_active; 64 65 std::variant<fd_func, fd_func2> func; 66 void* arg = nullptr; 67 }; 68 69 struct fdevent_context { 70 public: 71 virtual ~fdevent_context() = default; 72 73 // Allocate and initialize a new fdevent object. 74 fdevent* Create(unique_fd fd, std::variant<fd_func, fd_func2> func, void* arg); 75 76 // Deallocate an fdevent object, returning the file descriptor that was owned by it. 77 // Note that this calls Set, which is a virtual method, so destructors that call this must be 78 // final. 79 unique_fd Destroy(fdevent* fde); 80 81 protected: 82 virtual void Register(fdevent*) = 0; 83 virtual void Unregister(fdevent*) = 0; 84 85 public: 86 // Change which events should cause notifications. 87 virtual void Set(fdevent* fde, unsigned events) = 0; 88 void Add(fdevent* fde, unsigned events); 89 void Del(fdevent* fde, unsigned events); 90 91 // Set a timeout on an fdevent. 92 // If no events are triggered by the timeout, an FDE_TIMEOUT will be generated. 93 // Note timeouts are not defused automatically; if a timeout is set on an fdevent, it will 94 // trigger repeatedly every |timeout| ms. 95 void SetTimeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout); 96 97 protected: 98 std::optional<std::chrono::milliseconds> CalculatePollDuration(); 99 void HandleEvents(const std::vector<fdevent_event>& events); 100 101 private: 102 // Run all pending functions enqueued via Run(). 103 void FlushRunQueue() EXCLUDES(run_queue_mutex_); 104 105 public: 106 // Loop until TerminateLoop is called, handling events. 107 // Implementations should call FlushRunQueue on every iteration, and check the value of 108 // terminate_loop_ to determine whether to stop. 109 virtual void Loop() = 0; 110 111 // Assert that the caller is executing in the context of the execution 112 // thread that invoked Loop(). 113 void CheckLooperThread() const; 114 115 // Queue an operation to be run on the looper thread. 116 void Run(std::function<void()> fn); 117 118 // Test-only functionality: 119 void TerminateLoop(); 120 virtual size_t InstalledCount() = 0; 121 122 protected: 123 // Interrupt the run loop. 124 virtual void Interrupt() = 0; 125 126 std::optional<uint64_t> looper_thread_id_ = std::nullopt; 127 std::atomic<bool> terminate_loop_ = false; 128 129 std::map<int, fdevent> installed_fdevents_; 130 131 private: 132 uint64_t fdevent_id_ = 0; 133 std::mutex run_queue_mutex_; 134 std::deque<std::function<void()>> run_queue_ GUARDED_BY(run_queue_mutex_); 135 136 std::set<fdevent*> fdevent_set_; 137 }; 138 139 // Backwards compatibility shims that forward to the global fdevent_context. 140 fdevent* fdevent_create(int fd, fd_func func, void* arg); 141 fdevent* fdevent_create(int fd, fd_func2 func, void* arg); 142 143 unique_fd fdevent_release(fdevent* fde); 144 void fdevent_destroy(fdevent* fde); 145 146 void fdevent_set(fdevent *fde, unsigned events); 147 void fdevent_add(fdevent *fde, unsigned events); 148 void fdevent_del(fdevent *fde, unsigned events); 149 void fdevent_set_timeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout); 150 void fdevent_loop(); 151 152 // Delegates to the member function that checks for the initialization 153 // of Loop() so that fdevent_context requests can be serially processed 154 // by the global instance robustly. 155 void fdevent_check_looper(); 156 157 // Queue an operation to run on the looper event thread. 158 void fdevent_run_on_looper(std::function<void()> fn); 159 160 // The following functions are used only for tests. 161 void fdevent_terminate_loop(); 162 size_t fdevent_installed_count(); 163 void fdevent_reset(); 164 165 #endif 166