• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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