1 /* 2 * Copyright 2019 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 #pragma once 18 19 #include <sys/epoll.h> 20 21 #include <atomic> 22 #include <functional> 23 #include <future> 24 #include <list> 25 #include <memory> 26 #include <mutex> 27 #include <thread> 28 29 #include "common/callback.h" 30 #include "os/utils.h" 31 32 namespace bluetooth { 33 namespace os { 34 35 // A simple implementation of reactor-style looper. 36 // When a reactor is running, the main loop is polling and blocked until at least one registered 37 // reactable is ready to read or write. It will invoke on_read_ready() or on_write_ready(), which is 38 // registered with the reactor. Then, it blocks again until ready event. 39 class Reactor { 40 public: 41 // An object used for Unregister() and ModifyRegistration() 42 class Reactable; 43 44 // Construct a reactor on the current thread 45 Reactor(); 46 47 Reactor(const Reactor&) = delete; 48 Reactor& operator=(const Reactor&) = delete; 49 50 // Destruct this reactor and release its resources 51 ~Reactor(); 52 53 // Start the reactor. The current thread will be blocked until Stop() is invoked and handled. 54 void Run(); 55 56 // Stop the reactor. Must be invoked from a different thread. Note: all registered reactables will 57 // not be unregistered by Stop(). If the reactor is not running, it will be stopped once it's 58 // started. 59 void Stop(); 60 61 // Register a reactable fd to this reactor. Returns a pointer to a Reactable. Caller must use this 62 // object to unregister or modify registration. Ownership of the memory space is NOT transferred 63 // to user. 64 Reactable* Register(int fd, common::Closure on_read_ready, common::Closure on_write_ready); 65 66 // Unregister a reactable from this reactor 67 void Unregister(Reactable* reactable); 68 69 // Wait for up to timeout milliseconds, and return true if the reactable finished executing. 70 bool WaitForUnregisteredReactable(std::chrono::milliseconds timeout); 71 72 // Wait for up to timeout milliseconds, and return true if we reached idle. 73 bool WaitForIdle(std::chrono::milliseconds timeout); 74 75 enum ReactOn { 76 REACT_ON_READ_ONLY, 77 REACT_ON_WRITE_ONLY, 78 REACT_ON_READ_WRITE, 79 }; 80 81 // Modify subscribed poll events on the fly 82 void ModifyRegistration(Reactable* reactable, ReactOn react_on); 83 84 class Event { 85 public: 86 Event(); 87 ~Event(); 88 bool Read(); 89 int Id() const; 90 void Clear(); 91 void Close(); 92 void Notify(); 93 94 private: 95 Event(const Event& handler) = default; 96 struct impl; 97 impl* pimpl_{nullptr}; 98 }; 99 std::unique_ptr<Reactor::Event> NewEvent() const; 100 101 private: 102 mutable std::mutex mutex_; 103 int epoll_fd_; 104 int control_fd_; 105 std::atomic<bool> is_running_; 106 std::list<Reactable*> invalidation_list_; 107 std::shared_ptr<std::future<void>> executing_reactable_finished_; 108 std::shared_ptr<std::promise<void>> idle_promise_; 109 }; 110 111 } // namespace os 112 } // namespace bluetooth 113