Coverage Report

Created: 2025-12-10 07:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/node/src/node_threadsafe_cow.h
Line
Count
Source
1
#ifndef SRC_NODE_THREADSAFE_COW_H_
2
#define SRC_NODE_THREADSAFE_COW_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include "util.h"
7
#include "uv.h"
8
9
#include <memory>   // std::shared_ptr<T>
10
#include <utility>  // std::forward<T>
11
12
namespace node {
13
14
// Copy-on-write utility. Not threadsafe, i.e. there is no synchronization
15
// of the copy operation with other operations.
16
template <typename T>
17
class CopyOnWrite final {
18
 public:
19
  template <typename... Args>
20
  explicit CopyOnWrite(Args&&... args)
21
142
      : data_(std::make_shared<T>(std::forward<Args>(args)...)) {}
22
23
  CopyOnWrite(const CopyOnWrite<T>& other) = default;
24
70
  CopyOnWrite& operator=(const CopyOnWrite<T>& other) = default;
25
  CopyOnWrite(CopyOnWrite<T>&& other) = default;
26
  CopyOnWrite& operator=(CopyOnWrite<T>&& other) = default;
27
28
7.73k
  const T* read() const { return data_.get(); }
29
  T* write();
30
31
  const T& operator*() const { return *read(); }
32
7.73k
  const T* operator->() const { return read(); }
33
34
 private:
35
  std::shared_ptr<T> data_;
36
};
37
38
// Threadsafe copy-on-write utility. Consumers need to use the Read and
39
// Write helpers to access the target data structure.
40
template <typename T>
41
class ThreadsafeCopyOnWrite final {
42
 private:
43
  // Define this early since some of the public members depend on it
44
  // and some compilers need it to be defined first in that case.
45
  struct Impl {
46
    explicit Impl(const T& data) : data(data) {}
47
142
    explicit Impl(T&& data) : data(std::move(data)) {}
48
49
    Impl(const Impl& other);
50
    Impl& operator=(const Impl& other) = delete;
51
    Impl(Impl&& other) = delete;
52
    Impl& operator=(Impl&& other) = delete;
53
54
    RwLock mutex;
55
    T data;
56
  };
57
58
 public:
59
  template <typename... Args>
60
  ThreadsafeCopyOnWrite(Args&&... args)
61
142
      : impl_(T(std::forward<Args>(args)...)) {}
node::ThreadsafeCopyOnWrite<std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, node::builtins::BuiltinSource, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, node::builtins::BuiltinSource> > > >::ThreadsafeCopyOnWrite<>()
Line
Count
Source
61
70
      : impl_(T(std::forward<Args>(args)...)) {}
node::ThreadsafeCopyOnWrite<std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, node::builtins::BuiltinSource, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, node::builtins::BuiltinSource> > > >::ThreadsafeCopyOnWrite<std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, node::builtins::BuiltinSource, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, node::builtins::BuiltinSource> > > >(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, node::builtins::BuiltinSource, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, node::builtins::BuiltinSource> > >&&)
Line
Count
Source
61
72
      : impl_(T(std::forward<Args>(args)...)) {}
62
63
  ThreadsafeCopyOnWrite(const ThreadsafeCopyOnWrite<T>& other) = default;
64
  ThreadsafeCopyOnWrite& operator=(const ThreadsafeCopyOnWrite<T>& other) =
65
70
      default;
66
  ThreadsafeCopyOnWrite(ThreadsafeCopyOnWrite<T>&& other) = default;
67
  ThreadsafeCopyOnWrite& operator=(ThreadsafeCopyOnWrite<T>&& other) = default;
68
69
  class Read {
70
   public:
71
    explicit Read(const ThreadsafeCopyOnWrite<T>* cow);
72
73
    const T& operator*() const;
74
    const T* operator->() const;
75
76
   private:
77
    const ThreadsafeCopyOnWrite<T>* cow_;
78
    RwLock::ScopedReadLock lock_;
79
  };
80
81
  class Write {
82
   public:
83
    explicit Write(ThreadsafeCopyOnWrite<T>* cow);
84
85
    T& operator*();
86
    T* operator->();
87
88
   private:
89
    ThreadsafeCopyOnWrite<T>* cow_;
90
    typename ThreadsafeCopyOnWrite<T>::Impl* impl_;
91
    RwLock::ScopedLock lock_;
92
  };
93
94
2.59k
  Read read() const { return Read(this); }
95
0
  Write write() { return Write(this); }
96
97
 private:
98
  CopyOnWrite<Impl> impl_;
99
};
100
101
}  // namespace node
102
103
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
104
105
#endif  // SRC_NODE_THREADSAFE_COW_H_