YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/util/once.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  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,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
#ifndef YB_UTIL_ONCE_H
33
#define YB_UTIL_ONCE_H
34
35
#include <stddef.h>
36
37
#include "yb/gutil/once.h"
38
#include "yb/util/atomic.h"
39
#include "yb/util/status.h"
40
41
namespace yb {
42
43
class YBOnceDynamic;
44
45
namespace internal {
46
47
// Cheap, single-arg "bound callback" (similar to yb::Callback) for use
48
// in YBOnceDynamic.
49
template<typename T>
50
struct MemberFunc {
51
  YBOnceDynamic* once;
52
  T* instance;
53
  Status (T::*member_func)();
54
};
55
56
template<typename T>
57
3
void InitCb(void* arg) {
58
3
  MemberFunc<T>* mf = reinterpret_cast<MemberFunc<T>*>(arg);
59
3
  mf->once->status_ = (mf->instance->*mf->member_func)();
60
3
  mf->once->set_initted();
61
3
}
62
63
} // namespace internal
64
65
// More versatile version of GoogleOnceDynamic, including the following:
66
// 1. Can be used with single-arg, non-static member functions.
67
// 2. Retains results and overall initialization state for repeated access.
68
// 3. Access to initialization state is safe for concurrent use.
69
class YBOnceDynamic {
70
 public:
71
  YBOnceDynamic()
72
3
    : initted_(false) {
73
3
  }
74
75
  // If the underlying GoogleOnceDynamic has yet to be invoked, invokes the
76
  // provided member function and stores its return value. Otherwise,
77
  // returns the stored Status.
78
  //
79
  // T: the type of the member passed in.
80
  template<typename T>
81
9
  CHECKED_STATUS Init(Status (T::*member_func)(), T* instance) {
82
9
    internal::MemberFunc<T> mf = { this, instance, member_func };
83
84
    // Clang UBSAN doesn't like it when GoogleOnceDynamic handles the cast
85
    // of the argument:
86
    //
87
    //   runtime error: call to function
88
    //   yb::cfile::BloomFileReader::InitOnceCb(yb::cfile::BloomFileReader*)
89
    //   through pointer to incorrect function type 'void (*)(void *)'
90
    //
91
    // So let's do the cast ourselves, to void* here and back in InitCb().
92
9
    once_.Init(&internal::InitCb<T>, reinterpret_cast<void*>(&mf));
93
9
    return status_;
94
9
  }
95
96
  // kMemOrderAcquire ensures that loads/stores that come after initted()
97
  // aren't reordered to come before it instead. kMemOrderRelease ensures
98
  // the opposite (i.e. loads/stores before set_initted() aren't reordered
99
  // to come after it).
100
  //
101
  // Taken together, threads can safely synchronize on initted_.
102
10
  bool initted() const { return initted_.Load(kMemOrderAcquire); }
103
104
  // Returns the memory usage of this object without the object itself. Should
105
  // be used when embedded inside another object.
106
  size_t memory_footprint_excluding_this() const;
107
108
  // Returns the memory usage of this object including the object itself.
109
  // Should be used when allocated on the heap.
110
  size_t memory_footprint_including_this() const;
111
112
 private:
113
  template<typename T>
114
  friend void internal::InitCb(void* arg);
115
116
3
  void set_initted() { initted_.Store(true, kMemOrderRelease); }
117
118
  AtomicBool initted_;
119
  GoogleOnceDynamic once_;
120
  Status status_;
121
};
122
123
} // namespace yb
124
125
#endif