blob: 770e192deb8de2a473bbfb5611efd84aeeb18200 [file] [log] [blame]
David 'Digit' Turnerb1c2c952009-05-18 17:07:46 +02001/*
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
Yabin Cui2ce9d562015-09-15 16:27:09 -070020#include <stddef.h>
Josh Gao06d4e742019-01-31 15:51:52 -080021#include <stdint.h>
David 'Digit' Turner1f1efb52009-05-18 17:36:28 +020022
Anatol Pomazau324cb522019-08-08 14:45:12 -070023#include <atomic>
Josh Gao06d4e742019-01-31 15:51:52 -080024#include <chrono>
Josh Gaoc5e99e02019-07-08 17:37:23 -070025#include <deque>
Josh Gao764f8c52017-05-03 14:10:39 -070026#include <functional>
Colin Cross78d34d82023-05-16 22:10:26 +000027#include <map>
Josh Gaoc5e99e02019-07-08 17:37:23 -070028#include <mutex>
Josh Gao06d4e742019-01-31 15:51:52 -080029#include <optional>
Colin Cross9b245322023-05-16 22:10:31 +000030#include <set>
Josh Gao87a2db62019-01-25 15:30:25 -080031#include <variant>
Josh Gao764f8c52017-05-03 14:10:39 -070032
Josh Gaoc5e99e02019-07-08 17:37:23 -070033#include <android-base/thread_annotations.h>
34
Josh Gaod09ba312018-05-14 13:42:49 -070035#include "adb_unique_fd.h"
36
Josh Gao06d4e742019-01-31 15:51:52 -080037// 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
David 'Digit' Turnerb1c2c952009-05-18 17:07:46 +020042
Josh Gao4729f462019-07-11 16:35:37 -070043struct fdevent;
Josh Gao9e4aa3a2019-07-08 15:23:17 -070044
David 'Digit' Turnerb1c2c952009-05-18 17:07:46 +020045typedef void (*fd_func)(int fd, unsigned events, void *userdata);
Josh Gao87a2db62019-01-25 15:30:25 -080046typedef void (*fd_func2)(struct fdevent* fde, unsigned events, void* userdata);
David 'Digit' Turnerb1c2c952009-05-18 17:07:46 +020047
Josh Gao4729f462019-07-11 16:35:37 -070048void invoke_fde(struct fdevent* fde, unsigned events);
Josh Gao9e4aa3a2019-07-08 15:23:17 -070049std::string dump_fde(const fdevent* fde);
Josh Gaoc0810502019-06-28 16:34:36 -070050
Josh Gao4729f462019-07-11 16:35:37 -070051struct fdevent_event {
52 fdevent* fde;
53 unsigned events;
Matt Leec7bb7812023-05-16 21:02:04 +000054 fdevent_event(fdevent* pfde, unsigned ev) : fde(pfde), events(ev) {}
Josh Gao4729f462019-07-11 16:35:37 -070055};
56
Yurii Zubrytskyi22863bd2020-03-18 22:29:10 -070057struct fdevent final {
58 uint64_t id;
59
60 unique_fd fd;
Yurii Zubrytskyi22863bd2020-03-18 22:29:10 -070061
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
Josh Gaoc0810502019-06-28 16:34:36 -070070struct fdevent_context {
Josh Gaoc5e99e02019-07-08 17:37:23 -070071 public:
Josh Gaoc0810502019-06-28 16:34:36 -070072 virtual ~fdevent_context() = default;
73
74 // Allocate and initialize a new fdevent object.
Josh Gaoe10e56b2019-07-08 18:16:19 -070075 fdevent* Create(unique_fd fd, std::variant<fd_func, fd_func2> func, void* arg);
Josh Gaoc0810502019-06-28 16:34:36 -070076
77 // Deallocate an fdevent object, returning the file descriptor that was owned by it.
Josh Gaodd716422019-07-11 13:47:44 -070078 // Note that this calls Set, which is a virtual method, so destructors that call this must be
79 // final.
Josh Gaoe10e56b2019-07-08 18:16:19 -070080 unique_fd Destroy(fdevent* fde);
Josh Gaoc0810502019-06-28 16:34:36 -070081
Josh Gaoe10e56b2019-07-08 18:16:19 -070082 protected:
Elliott Hughesf24aebf2020-05-12 16:17:11 -070083 virtual void Register(fdevent*) = 0;
84 virtual void Unregister(fdevent*) = 0;
Josh Gaoe10e56b2019-07-08 18:16:19 -070085
86 public:
Josh Gaoc0810502019-06-28 16:34:36 -070087 // Change which events should cause notifications.
88 virtual void Set(fdevent* fde, unsigned events) = 0;
Josh Gaoad93dc52019-07-08 18:17:41 -070089 void Add(fdevent* fde, unsigned events);
90 void Del(fdevent* fde, unsigned events);
Josh Gaoc0810502019-06-28 16:34:36 -070091
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.
Josh Gaoad93dc52019-07-08 18:17:41 -070096 void SetTimeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout);
Josh Gaoc0810502019-06-28 16:34:36 -070097
Josh Gao4729f462019-07-11 16:35:37 -070098 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:
Josh Gaodf92f8a2019-07-08 18:08:06 -0700107 // 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.
Josh Gaoc0810502019-06-28 16:34:36 -0700110 virtual void Loop() = 0;
111
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800112 // Assert that the caller is executing in the context of the execution
113 // thread that invoked Loop().
114 void CheckLooperThread() const;
Josh Gaoc0810502019-06-28 16:34:36 -0700115
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800116 // Queue an operation to be run on the looper thread.
Josh Gaoc5e99e02019-07-08 17:37:23 -0700117 void Run(std::function<void()> fn);
Josh Gaoc0810502019-06-28 16:34:36 -0700118
119 // Test-only functionality:
Josh Gaodf92f8a2019-07-08 18:08:06 -0700120 void TerminateLoop();
Josh Gaoc0810502019-06-28 16:34:36 -0700121 virtual size_t InstalledCount() = 0;
Josh Gaoc5e99e02019-07-08 17:37:23 -0700122
123 protected:
124 // Interrupt the run loop.
125 virtual void Interrupt() = 0;
126
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800127 std::optional<uint64_t> looper_thread_id_ = std::nullopt;
Josh Gaodf92f8a2019-07-08 18:08:06 -0700128 std::atomic<bool> terminate_loop_ = false;
Josh Gao83e435a2019-07-08 18:05:16 -0700129
Colin Cross78d34d82023-05-16 22:10:26 +0000130 std::map<int, fdevent> installed_fdevents_;
Josh Gao4729f462019-07-11 16:35:37 -0700131
Josh Gaoc5e99e02019-07-08 17:37:23 -0700132 private:
Josh Gaoe10e56b2019-07-08 18:16:19 -0700133 uint64_t fdevent_id_ = 0;
Josh Gaoc5e99e02019-07-08 17:37:23 -0700134 std::mutex run_queue_mutex_;
135 std::deque<std::function<void()>> run_queue_ GUARDED_BY(run_queue_mutex_);
Colin Cross9b245322023-05-16 22:10:31 +0000136
137 std::set<fdevent*> fdevent_set_;
Josh Gaoc0810502019-06-28 16:34:36 -0700138};
139
Josh Gaoc0810502019-06-28 16:34:36 -0700140// Backwards compatibility shims that forward to the global fdevent_context.
141fdevent* fdevent_create(int fd, fd_func func, void* arg);
Josh Gao87a2db62019-01-25 15:30:25 -0800142fdevent* fdevent_create(int fd, fd_func2 func, void* arg);
David 'Digit' Turnerb1c2c952009-05-18 17:07:46 +0200143
Josh Gaoed15cac2018-09-20 17:38:55 -0700144unique_fd fdevent_release(fdevent* fde);
Josh Gaoc0810502019-06-28 16:34:36 -0700145void fdevent_destroy(fdevent* fde);
Josh Gaoed15cac2018-09-20 17:38:55 -0700146
David 'Digit' Turnerb1c2c952009-05-18 17:07:46 +0200147void fdevent_set(fdevent *fde, unsigned events);
148void fdevent_add(fdevent *fde, unsigned events);
149void fdevent_del(fdevent *fde, unsigned events);
Josh Gao06d4e742019-01-31 15:51:52 -0800150void fdevent_set_timeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout);
David 'Digit' Turnerb1c2c952009-05-18 17:07:46 +0200151void fdevent_loop();
Yabin Cui3cf1b362017-03-10 16:01:01 -0800152
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800153// 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.
156void fdevent_check_looper();
157
158// Queue an operation to run on the looper event thread.
159void fdevent_run_on_looper(std::function<void()> fn);
Josh Gao764f8c52017-05-03 14:10:39 -0700160
Josh Gao511763b2016-02-10 14:49:00 -0800161// The following functions are used only for tests.
162void fdevent_terminate_loop();
Yabin Cui2ce9d562015-09-15 16:27:09 -0700163size_t fdevent_installed_count();
Yabin Cui2ce9d562015-09-15 16:27:09 -0700164void fdevent_reset();
David 'Digit' Turnerb1c2c952009-05-18 17:07:46 +0200165
David 'Digit' Turnerb1c2c952009-05-18 17:07:46 +0200166#endif