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 reactable is ready to 37 // read or write. It will invoke on_read_ready() or on_write_ready(), which is registered with the reactor. Then, it 38 // 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 not be unregistered 57 // by Stop(). If the reactor is not running, it will be stopped once it's started. 58 void Stop(); 59 60 // Register a reactable fd to this reactor. Returns a pointer to a Reactable. Caller must use this object to 61 // unregister or modify registration. Ownership of the memory space is NOT transferred to user. 62 Reactable* Register(int fd, common::Closure on_read_ready, common::Closure on_write_ready); 63 64 // Unregister a reactable from this reactor 65 void Unregister(Reactable* reactable); 66 67 // Wait for up to timeout milliseconds, and return true if the reactable finished executing. 68 bool WaitForUnregisteredReactable(std::chrono::milliseconds timeout); 69 70 // Wait for up to timeout milliseconds, and return true if we reached idle. 71 bool WaitForIdle(std::chrono::milliseconds timeout); 72 73 enum ReactOn { 74 REACT_ON_READ_ONLY, 75 REACT_ON_WRITE_ONLY, 76 REACT_ON_READ_WRITE, 77 }; 78 79 // Modify subscribed poll events on the fly 80 void ModifyRegistration(Reactable* reactable, ReactOn react_on); 81 82 class Event { 83 public: 84 Event(); 85 ~Event(); 86 bool Read(); 87 int Id() const; 88 void Clear(); 89 void Close(); 90 void Notify(); 91 92 private: 93 Event(const Event& handler) = default; 94 struct impl; 95 impl* pimpl_{nullptr}; 96 }; 97 std::unique_ptr<Reactor::Event> NewEvent() const; 98 99 private: 100 mutable std::mutex mutex_; 101 int epoll_fd_; 102 int control_fd_; 103 std::atomic<bool> is_running_; 104 std::list<Reactable*> invalidation_list_; 105 std::shared_ptr<std::future<void>> executing_reactable_finished_; 106 std::shared_ptr<std::promise<void>> idle_promise_; 107 }; 108 109 } // namespace os 110 } // namespace bluetooth 111