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/event_engine/event_engine.h> 23 #include <grpc/support/port_platform.h> 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 #include "src/core/lib/event_engine/forkable.h" 32 #include "src/core/lib/event_engine/posix_engine/timer.h" 33 #include "src/core/lib/event_engine/thread_pool/thread_pool.h" 34 #include "src/core/util/notification.h" 35 #include "src/core/util/sync.h" 36 #include "src/core/util/time.h" 37 38 namespace grpc_event_engine { 39 namespace experimental { 40 41 // Timer Manager tries to keep only one thread waiting for the next timeout at 42 // all times, and thus effectively preventing the thundering herd problem. 43 // TODO(ctiller): consider unifying this thread pool and the one in 44 // thread_pool.{h,cc}. 45 class TimerManager final : public grpc_event_engine::experimental::Forkable { 46 public: 47 explicit TimerManager( 48 std::shared_ptr<grpc_event_engine::experimental::ThreadPool> thread_pool); 49 ~TimerManager() override; 50 Now()51 grpc_core::Timestamp Now() { return host_.Now(); } 52 53 void TimerInit(Timer* timer, grpc_core::Timestamp deadline, 54 experimental::EventEngine::Closure* closure); 55 bool TimerCancel(Timer* timer); 56 57 static bool IsTimerManagerThread(); 58 59 // Called on destruction, prefork, and manually when needed. 60 void Shutdown(); 61 62 void PrepareFork() override; 63 void PostforkParent() override; 64 void PostforkChild() override; 65 66 private: 67 class Host final : public TimerListHost { 68 public: Host(TimerManager * timer_manager)69 explicit Host(TimerManager* timer_manager) 70 : timer_manager_(timer_manager) {} 71 72 void Kick() override; 73 grpc_core::Timestamp Now() override; 74 75 private: 76 TimerManager* const timer_manager_; 77 }; 78 79 void RestartPostFork(); 80 void MainLoop(); 81 void RunSomeTimers(std::vector<experimental::EventEngine::Closure*> timers); 82 bool WaitUntil(grpc_core::Timestamp next); 83 void Kick(); 84 85 grpc_core::Mutex mu_; 86 // Condvar associated with the main thread waiting to wakeup and work. 87 // Threads wait on this until either a timeout is reached or the timer manager 88 // is kicked. On shutdown we Signal against this to wake up all threads and 89 // have them finish. On kick we Signal against this to wake up the main 90 // thread. 91 grpc_core::CondVar cv_wait_; 92 Host host_; 93 // are we shutting down? 94 bool shutdown_ ABSL_GUARDED_BY(mu_) = false; 95 // are we shutting down? 96 bool kicked_ ABSL_GUARDED_BY(mu_) = false; 97 // number of timer wakeups 98 uint64_t wakeups_ ABSL_GUARDED_BY(mu_) = false; 99 // actual timer implementation 100 std::unique_ptr<TimerList> timer_list_; 101 std::shared_ptr<grpc_event_engine::experimental::ThreadPool> thread_pool_; 102 absl::optional<grpc_core::Notification> main_loop_exit_signal_; 103 }; 104 105 } // namespace experimental 106 } // namespace grpc_event_engine 107 108 #endif // GRPC_SRC_CORE_LIB_EVENT_ENGINE_POSIX_ENGINE_TIMER_MANAGER_H 109