/Users/deen/code/yugabyte-db/src/yb/util/ev_util.h
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // Copyright (c) YugaByte, Inc. |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
5 | | // in compliance with the License. You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
10 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
11 | | // or implied. See the License for the specific language governing permissions and limitations |
12 | | // under the License. |
13 | | // |
14 | | // |
15 | | |
16 | | #ifndef YB_UTIL_EV_UTIL_H |
17 | | #define YB_UTIL_EV_UTIL_H |
18 | | |
19 | | #include <ev++.h> |
20 | | |
21 | | #include "yb/util/atomic.h" |
22 | | #include "yb/util/monotime.h" |
23 | | |
24 | | namespace yb { |
25 | | |
26 | | // We need to do all operations with ev::timer from the same thread, but for example RPC connection |
27 | | // could be held by shared_ptr inside RPC calls even after reactor is shutdown. Connection |
28 | | // destructor could be invoked from another thread after shutdown. |
29 | | // EvTimerHolder provides a shutdown function to destroy embedded timer, so it won't be destroyed |
30 | | // on holder destruction. |
31 | | // This class is not thread-safe, but allowed to be destructed from any thread given that it was |
32 | | // previously shutdown from owning thread. |
33 | | class EvTimerHolder { |
34 | | public: |
35 | 1.88M | EvTimerHolder() {} |
36 | | |
37 | 1.23M | ~EvTimerHolder() { |
38 | 1.23M | auto* timer = timer_.get(); |
39 | 18.4E | LOG_IF(DFATAL, timer) << "Timer " << timer << " should be already shutdown " << this; |
40 | 1.23M | } |
41 | | |
42 | | // Should be called before first usage of timer. |
43 | | void Init(const ev::loop_ref& loop); |
44 | | |
45 | | // Should be invoked from the timer loop thread before holder destruction. |
46 | | // Safe to call multiple times. |
47 | | void Shutdown(); |
48 | | |
49 | 114M | bool IsInitialized() { |
50 | 114M | return timer_.get(); |
51 | 114M | } |
52 | | |
53 | | // Starts timer after `left` time period. |
54 | 113M | void Start(CoarseMonoClock::Duration left) { |
55 | 113M | GetInitialized()->start(MonoDelta(left).ToSeconds(), 0 /* repeat */); |
56 | 113M | } |
57 | | |
58 | | // Sets method of the `object` as a callback for timer. |
59 | | template<class T, void (T::*Method)(ev::timer &w, int)> // NOLINT |
60 | 1.54M | void SetCallback(T* object) { |
61 | 1.54M | GetInitialized()->set<T, Method>(object); |
62 | 1.54M | } _ZN2yb13EvTimerHolder11SetCallbackINS_3rpc10ConnectionEXadL_ZNS3_13HandleTimeoutERN2ev5timerEiEEEEvPT_ Line | Count | Source | 60 | 940k | void SetCallback(T* object) { | 61 | 940k | GetInitialized()->set<T, Method>(object); | 62 | 940k | } |
_ZN2yb13EvTimerHolder11SetCallbackINS_3rpc26YBInboundConnectionContextEXadL_ZNS3_13HandleTimeoutERN2ev5timerEiEEEEvPT_ Line | Count | Source | 60 | 304k | void SetCallback(T* object) { | 61 | 304k | GetInitialized()->set<T, Method>(object); | 62 | 304k | } |
_ZN2yb13EvTimerHolder11SetCallbackINS_3rpc27YBOutboundConnectionContextEXadL_ZNS3_13HandleTimeoutERN2ev5timerEiEEEEvPT_ Line | Count | Source | 60 | 298k | void SetCallback(T* object) { | 61 | 298k | GetInitialized()->set<T, Method>(object); | 62 | 298k | } |
|
63 | | |
64 | 0 | ev::timer& operator*() { |
65 | 0 | return *GetInitialized(); |
66 | 0 | } |
67 | | |
68 | 0 | ev::timer* operator->() { |
69 | 0 | return GetInitialized(); |
70 | 0 | } |
71 | | |
72 | | private: |
73 | 114M | ev::timer* GetInitialized() { |
74 | 4.03k | LOG_IF(DFATAL, !IsInitialized()) << "Timer should be previously initialized"; |
75 | 114M | return timer_.get(); |
76 | 114M | } |
77 | | |
78 | | AtomicUniquePtr<ev::timer> timer_; |
79 | | }; |
80 | | |
81 | | } // namespace yb |
82 | | |
83 | | #endif // YB_UTIL_EV_UTIL_H |