1 // 2 // 3 // Copyright 2017 gRPC authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // 17 // 18 19 #ifndef GRPC_SRC_CORE_LIB_EVENT_ENGINE_POSIX_ENGINE_TIMER_MANAGER_H 20 #define GRPC_SRC_CORE_LIB_EVENT_ENGINE_POSIX_ENGINE_TIMER_MANAGER_H 21 22 #include <grpc/support/port_platform.h> 23 24 #include <stdint.h> 25 26 #include <memory> 27 #include <vector> 28 29 #include "absl/base/thread_annotations.h" 30 #include "absl/types/optional.h" 31 32 #include <grpc/event_engine/event_engine.h> 33 34 #include "src/core/lib/event_engine/forkable.h" 35 #include "src/core/lib/event_engine/posix_engine/timer.h" 36 #include "src/core/lib/event_engine/thread_pool/thread_pool.h" 37 #include "src/core/lib/gprpp/notification.h" 38 #include "src/core/lib/gprpp/sync.h" 39 #include "src/core/lib/gprpp/thd.h" 40 #include "src/core/lib/gprpp/time.h" 41 42 namespace grpc_event_engine { 43 namespace experimental { 44 45 // Timer Manager tries to keep only one thread waiting for the next timeout at 46 // all times, and thus effectively preventing the thundering herd problem. 47 // TODO(ctiller): consider unifying this thread pool and the one in 48 // thread_pool.{h,cc}. 49 class TimerManager final : public grpc_event_engine::experimental::Forkable { 50 public: 51 explicit TimerManager( 52 std::shared_ptr<grpc_event_engine::experimental::ThreadPool> thread_pool); 53 ~TimerManager() override; 54 Now()55 grpc_core::Timestamp Now() { return host_.Now(); } 56 57 void TimerInit(Timer* timer, grpc_core::Timestamp deadline, 58 experimental::EventEngine::Closure* closure); 59 bool TimerCancel(Timer* timer); 60 61 static bool IsTimerManagerThread(); 62 63 // Called on destruction, prefork, and manually when needed. 64 void Shutdown(); 65 66 void PrepareFork() override; 67 void PostforkParent() override; 68 void PostforkChild() override; 69 70 private: 71 class Host final : public TimerListHost { 72 public: Host(TimerManager * timer_manager)73 explicit Host(TimerManager* timer_manager) 74 : timer_manager_(timer_manager) {} 75 76 void Kick() override; 77 grpc_core::Timestamp Now() override; 78 79 private: 80 TimerManager* const timer_manager_; 81 }; 82 83 void StartMainLoopThread(); 84 void RestartPostFork(); 85 void MainLoop(); 86 void RunSomeTimers(std::vector<experimental::EventEngine::Closure*> timers); 87 bool WaitUntil(grpc_core::Timestamp next); 88 void Kick(); 89 90 grpc_core::Mutex mu_; 91 // Condvar associated with the main thread waiting to wakeup and work. 92 // Threads wait on this until either a timeout is reached or the timer manager 93 // is kicked. On shutdown we Signal against this to wake up all threads and 94 // have them finish. On kick we Signal against this to wake up the main 95 // thread. 96 grpc_core::CondVar cv_wait_; 97 Host host_; 98 // are we shutting down? 99 bool shutdown_ ABSL_GUARDED_BY(mu_) = false; 100 // are we shutting down? 101 bool kicked_ ABSL_GUARDED_BY(mu_) = false; 102 // number of timer wakeups 103 uint64_t wakeups_ ABSL_GUARDED_BY(mu_) = false; 104 // actual timer implementation 105 std::unique_ptr<TimerList> timer_list_; 106 grpc_core::Thread main_thread_; 107 std::shared_ptr<grpc_event_engine::experimental::ThreadPool> thread_pool_; 108 absl::optional<grpc_core::Notification> main_loop_exit_signal_; 109 }; 110 111 } // namespace experimental 112 } // namespace grpc_event_engine 113 114 #endif // GRPC_SRC_CORE_LIB_EVENT_ENGINE_POSIX_ENGINE_TIMER_MANAGER_H 115