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 <mutex> 26 #include <thread> 27 28 #include "common/callback.h" 29 #include "os/utils.h" 30 31 namespace bluetooth { 32 namespace os { 33 34 // A simple implementation of reactor-style looper. 35 // When a reactor is running, the main loop is polling and blocked until at least one registered reactable is ready to 36 // read or write. It will invoke on_read_ready() or on_write_ready(), which is registered with the reactor. Then, it 37 // blocks again until ready event. 38 class Reactor { 39 public: 40 // An object used for Unregister() and ModifyRegistration() 41 class Reactable; 42 43 // Construct a reactor on the current thread 44 Reactor(); 45 46 // Destruct this reactor and release its resources 47 ~Reactor(); 48 49 DISALLOW_COPY_AND_ASSIGN(Reactor); 50 51 // Start the reactor. The current thread will be blocked until Stop() is invoked and handled. 52 void Run(); 53 54 // Stop the reactor. Must be invoked from a different thread. Note: all registered reactables will not be unregistered 55 // by Stop(). If the reactor is not running, it will be stopped once it's started. 56 void Stop(); 57 58 // Register a reactable fd to this reactor. Returns a pointer to a Reactable. Caller must use this object to 59 // unregister or modify registration. Ownership of the memory space is NOT transferred to user. 60 Reactable* Register(int fd, common::Closure on_read_ready, common::Closure on_write_ready); 61 62 // Unregister a reactable from this reactor 63 void Unregister(Reactable* reactable); 64 65 // Wait for up to timeout milliseconds, and return true if the reactable finished executing. 66 bool WaitForUnregisteredReactable(std::chrono::milliseconds timeout); 67 68 // Wait for up to timeout milliseconds, and return true if we reached idle. 69 bool WaitForIdle(std::chrono::milliseconds timeout); 70 71 // Modify the registration for a reactable with given reactable 72 void ModifyRegistration(Reactable* reactable, common::Closure on_read_ready, common::Closure on_write_ready); 73 74 private: 75 mutable std::mutex mutex_; 76 int epoll_fd_; 77 int control_fd_; 78 std::atomic<bool> is_running_; 79 std::list<Reactable*> invalidation_list_; 80 std::shared_ptr<std::future<void>> executing_reactable_finished_; 81 std::shared_ptr<std::promise<void>> idle_promise_; 82 }; 83 84 } // namespace os 85 } // namespace bluetooth 86