GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/fence.h
Date: 2024-04-21 02:33:16
Exec Total Coverage
Lines: 27 29 93.1%
Branches: 2 4 50.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #ifndef CVMFS_FENCE_H_
6 #define CVMFS_FENCE_H_
7
8 #include "gtest/gtest_prod.h"
9 #include "util/atomic.h"
10 #include "util/posix.h"
11 #include "util/single_copy.h"
12
13 #ifdef CVMFS_NAMESPACE_GUARD
14 namespace CVMFS_NAMESPACE_GUARD {
15 #endif
16
17 /**
18 * A Fence can be used to protect critical regions where blocking is a very
19 * rare operation. When the Fence is not blocked, entering and leaving a
20 * critical region requires only a 1-2 atomic operations. In order to block
21 * the fence, no new threads can enter a critical region. When all entered
22 * regions are left, the fence is blocked. Waiting is done through slow busy
23 * wait.
24 */
25 class Fence : public SingleCopy {
26 FRIEND_TEST(T_Fence, Basics);
27
28 public:
29 1 Fence() {
30 1 atomic_init64(&counter_);
31 1 atomic_init32(&blocking_);
32 1 }
33
34 2 void Enter() {
35
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 while (atomic_read32(&blocking_)) {
36 SafeSleepMs(kBusyWaitBackoffMs);
37 }
38 2 atomic_inc64(&counter_);
39 2 }
40
41 2 void Leave() {
42 2 atomic_dec64(&counter_);
43 2 }
44
45 2 void Close() {
46 2 atomic_cas32(&blocking_, 0, 1);
47 2 }
48
49 /**
50 * Close and let live critical regions exit
51 */
52 1 void Drain() {
53 1 Close();
54
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 while (atomic_read64(&counter_) > 0) {
55 SafeSleepMs(kBusyWaitBackoffMs);
56 }
57 1 }
58
59 2 void Open() {
60 2 atomic_cas32(&blocking_, 1, 0);
61 2 }
62
63 private:
64 static const unsigned kBusyWaitBackoffMs = 100;
65
66 /**
67 * Number of active critical regions.
68 */
69 atomic_int64 counter_;
70
71 /**
72 * A boolean that indicates if the fence is blocked.
73 */
74 atomic_int32 blocking_;
75 };
76
77
78 /**
79 * RAII wrapper in case an entire function or code block should be protected
80 * by a fence.
81 */
82 class FenceGuard {
83 public:
84 1 explicit FenceGuard(Fence *fence) : fence_(fence) {
85 1 fence_->Enter();
86 1 }
87 1 ~FenceGuard() {
88 1 fence_->Leave();
89 1 }
90 private:
91 Fence *fence_;
92 };
93
94 #ifdef CVMFS_NAMESPACE_GUARD
95 } // namespace CVMFS_NAMESPACE_GUARD
96 #endif
97
98 #endif // CVMFS_FENCE_H_
99