diff --git a/adb/fdevent/fdevent.cpp b/adb/fdevent/fdevent.cpp index d2f81e004..26ebc49d7 100644 --- a/adb/fdevent/fdevent.cpp +++ b/adb/fdevent/fdevent.cpp @@ -24,6 +24,7 @@ #include #include +#include "adb_utils.h" #include "fdevent.h" #include "fdevent_poll.h" @@ -48,6 +49,40 @@ std::string dump_fde(const fdevent* fde) { state.c_str()); } +fdevent* fdevent_context::Create(unique_fd fd, std::variant func, void* arg) { + CheckMainThread(); + CHECK_GE(fd.get(), 0); + + fdevent* fde = new fdevent(); + fde->id = fdevent_id_++; + fde->state = FDE_ACTIVE; + fde->fd = std::move(fd); + fde->func = func; + fde->arg = arg; + if (!set_file_block_mode(fde->fd, false)) { + // Here is not proper to handle the error. If it fails here, some error is + // likely to be detected by poll(), then we can let the callback function + // to handle it. + LOG(ERROR) << "failed to set non-blocking mode for fd " << fde->fd.get(); + } + + this->Register(fde); + return fde; +} + +unique_fd fdevent_context::Destroy(fdevent* fde) { + CheckMainThread(); + if (!fde) { + return {}; + } + + this->Unregister(fde); + + unique_fd result = std::move(fde->fd); + delete fde; + return result; +} + void fdevent_context::CheckMainThread() { if (main_thread_id_) { CHECK_EQ(*main_thread_id_, android::base::GetThreadId()); diff --git a/adb/fdevent/fdevent.h b/adb/fdevent/fdevent.h index e84cff799..3a3682fcc 100644 --- a/adb/fdevent/fdevent.h +++ b/adb/fdevent/fdevent.h @@ -55,11 +55,19 @@ struct fdevent_context { virtual ~fdevent_context() = default; // Allocate and initialize a new fdevent object. - virtual fdevent* Create(unique_fd fd, std::variant func, void* arg) = 0; + fdevent* Create(unique_fd fd, std::variant func, void* arg); // Deallocate an fdevent object, returning the file descriptor that was owned by it. - virtual unique_fd Destroy(fdevent* fde) = 0; + unique_fd Destroy(fdevent* fde); + protected: + // Register an fdevent that is being created by Create with the fdevent_context. + virtual void Register(fdevent* fde) = 0; + + // Unregister an fdevent that is being destroyed by Destroy with the fdevent_context. + virtual void Unregister(fdevent* fde) = 0; + + public: // Change which events should cause notifications. virtual void Set(fdevent* fde, unsigned events) = 0; virtual void Add(fdevent* fde, unsigned events) = 0; @@ -98,6 +106,7 @@ struct fdevent_context { std::atomic terminate_loop_ = false; private: + uint64_t fdevent_id_ = 0; std::mutex run_queue_mutex_; std::deque> run_queue_ GUARDED_BY(run_queue_mutex_); }; diff --git a/adb/fdevent/fdevent_poll.cpp b/adb/fdevent/fdevent_poll.cpp index 43fd462a0..59b6b933f 100644 --- a/adb/fdevent/fdevent_poll.cpp +++ b/adb/fdevent/fdevent_poll.cpp @@ -78,38 +78,14 @@ fdevent_context_poll::~fdevent_context_poll() { this->Destroy(this->interrupt_fde_); } -fdevent* fdevent_context_poll::Create(unique_fd fd, std::variant func, - void* arg) { - CheckMainThread(); - CHECK_GE(fd.get(), 0); - - fdevent* fde = new fdevent(); - fde->id = fdevent_id_++; - fde->state = FDE_ACTIVE; - fde->fd = std::move(fd); - fde->func = func; - fde->arg = arg; - if (!set_file_block_mode(fde->fd, false)) { - // Here is not proper to handle the error. If it fails here, some error is - // likely to be detected by poll(), then we can let the callback function - // to handle it. - LOG(ERROR) << "failed to set non-blocking mode for fd " << fde->fd.get(); - } +void fdevent_context_poll::Register(fdevent* fde) { auto pair = poll_node_map_.emplace(fde->fd.get(), PollNode(fde)); CHECK(pair.second) << "install existing fd " << fde->fd.get(); - - return fde; } -unique_fd fdevent_context_poll::Destroy(fdevent* fde) { - CheckMainThread(); - if (!fde) { - return {}; - } - - unique_fd result = std::move(fde->fd); +void fdevent_context_poll::Unregister(fdevent* fde) { if (fde->state & FDE_ACTIVE) { - poll_node_map_.erase(result.get()); + poll_node_map_.erase(fde->fd.get()); if (fde->state & FDE_PENDING) { pending_list_.remove(fde); @@ -117,9 +93,6 @@ unique_fd fdevent_context_poll::Destroy(fdevent* fde) { fde->state = 0; fde->events = 0; } - - delete fde; - return result; } void fdevent_context_poll::Set(fdevent* fde, unsigned events) { diff --git a/adb/fdevent/fdevent_poll.h b/adb/fdevent/fdevent_poll.h index 9ae47baaf..bffc873c6 100644 --- a/adb/fdevent/fdevent_poll.h +++ b/adb/fdevent/fdevent_poll.h @@ -48,8 +48,8 @@ struct fdevent_context_poll : public fdevent_context { fdevent_context_poll(); virtual ~fdevent_context_poll(); - virtual fdevent* Create(unique_fd fd, std::variant func, void* arg) final; - virtual unique_fd Destroy(fdevent* fde) final; + virtual void Register(fdevent* fde) final; + virtual void Unregister(fdevent* fde) final; virtual void Set(fdevent* fde, unsigned events) final; virtual void Add(fdevent* fde, unsigned events) final; @@ -68,7 +68,6 @@ struct fdevent_context_poll : public fdevent_context { // That's why we don't need a lock for fdevent. std::unordered_map poll_node_map_; std::list pending_list_; - uint64_t fdevent_id_ = 0; unique_fd interrupt_fd_; fdevent* interrupt_fde_ = nullptr;