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