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