YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/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
7.51M
  EvTimerHolder() {}
36
37
6.50M
  ~EvTimerHolder() {
38
6.50M
    auto* timer = timer_.get();
39
18.4E
    LOG_IF(DFATAL, timer) << "Timer " << timer << " should be already shutdown " << this;
40
6.50M
  }
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
1.15G
  bool IsInitialized() {
50
1.15G
    return timer_.get();
51
1.15G
  }
52
53
  // Starts timer after `left` time period.
54
1.15G
  void Start(CoarseMonoClock::Duration left) {
55
1.15G
    GetInitialized()->start(MonoDelta(left).ToSeconds(), 0 /* repeat */);
56
1.15G
  }
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
4.96M
  void SetCallback(T* object) {
61
4.96M
    GetInitialized()->set<T, Method>(object);
62
4.96M
  }
void yb::EvTimerHolder::SetCallback<yb::rpc::Connection, &(yb::rpc::Connection::HandleTimeout(ev::timer&, int))>(yb::rpc::Connection*)
Line
Count
Source
60
3.74M
  void SetCallback(T* object) {
61
3.74M
    GetInitialized()->set<T, Method>(object);
62
3.74M
  }
void yb::EvTimerHolder::SetCallback<yb::rpc::YBInboundConnectionContext, &(yb::rpc::YBInboundConnectionContext::HandleTimeout(ev::timer&, int))>(yb::rpc::YBInboundConnectionContext*)
Line
Count
Source
60
609k
  void SetCallback(T* object) {
61
609k
    GetInitialized()->set<T, Method>(object);
62
609k
  }
void yb::EvTimerHolder::SetCallback<yb::rpc::YBOutboundConnectionContext, &(yb::rpc::YBOutboundConnectionContext::HandleTimeout(ev::timer&, int))>(yb::rpc::YBOutboundConnectionContext*)
Line
Count
Source
60
605k
  void SetCallback(T* object) {
61
605k
    GetInitialized()->set<T, Method>(object);
62
605k
  }
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
1.15G
  ev::timer* GetInitialized() {
74
1.15G
    LOG_IF
(DFATAL, !IsInitialized()) << "Timer should be previously initialized"156k
;
75
1.15G
    return timer_.get();
76
1.15G
  }
77
78
  AtomicUniquePtr<ev::timer> timer_;
79
};
80
81
} // namespace yb
82
83
#endif // YB_UTIL_EV_UTIL_H