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 <mutex> 28 #include <optional> 29 #include <unordered_map> 30 #include <variant> 31 32 #include <android-base/thread_annotations.h> 33 34 #include "adb_unique_fd.h" 35 36 // Events that may be observed 37 #define FDE_READ 0x0001 38 #define FDE_WRITE 0x0002 39 #define FDE_ERROR 0x0004 40 #define FDE_TIMEOUT 0x0008 41 42 struct fdevent; 43 44 typedef void (*fd_func)(int fd, unsigned events, void *userdata); 45 typedef void (*fd_func2)(struct fdevent* fde, unsigned events, void* userdata); 46 47 void invoke_fde(struct fdevent* fde, unsigned events); 48 std::string dump_fde(const fdevent* fde); 49 50 struct fdevent_event { 51 fdevent* fde; 52 unsigned events; 53 }; 54 55 struct fdevent final { 56 uint64_t id; 57 58 unique_fd fd; 59 int force_eof = 0; 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 either running on the context's main thread, or that there is no 112 // active main thread. 113 void CheckMainThread(); 114 115 // Queue an operation to be run on the main 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> main_thread_id_ = std::nullopt; 127 std::atomic<bool> terminate_loop_ = false; 128 129 protected: 130 std::unordered_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 138 // Backwards compatibility shims that forward to the global fdevent_context. 139 fdevent* fdevent_create(int fd, fd_func func, void* arg); 140 fdevent* fdevent_create(int fd, fd_func2 func, void* arg); 141 142 unique_fd fdevent_release(fdevent* fde); 143 void fdevent_destroy(fdevent* fde); 144 145 void fdevent_set(fdevent *fde, unsigned events); 146 void fdevent_add(fdevent *fde, unsigned events); 147 void fdevent_del(fdevent *fde, unsigned events); 148 void fdevent_set_timeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout); 149 void fdevent_loop(); 150 void check_main_thread(); 151 152 // Queue an operation to run on the main thread. 153 void fdevent_run_on_main_thread(std::function<void()> fn); 154 155 // The following functions are used only for tests. 156 void fdevent_terminate_loop(); 157 size_t fdevent_installed_count(); 158 void fdevent_reset(); 159 160 #endif 161