Coverage Report

Created: 2025-11-09 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/brpc/src/butil/synchronization/lock.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
#ifndef BUTIL_SYNCHRONIZATION_LOCK_H_
19
#define BUTIL_SYNCHRONIZATION_LOCK_H_
20
21
#include "butil/build_config.h"
22
#if defined(OS_WIN)
23
#include <windows.h>
24
#elif defined(OS_POSIX)
25
#include <pthread.h>
26
#if defined(OS_LINUX) && defined(__USE_XOPEN2K)
27
#define HAS_PTHREAD_MUTEX_TIMEDLOCK 1
28
#else
29
#define HAS_PTHREAD_MUTEX_TIMEDLOCK 0
30
#endif // OS_LINUX __USE_XOPEN2K
31
#endif // OS_POSIX
32
33
#include "butil/base_export.h"
34
#include "butil/macros.h"
35
#include "butil/compat.h"
36
37
namespace butil {
38
39
// A convenient wrapper for an OS specific critical section.  
40
class BUTIL_EXPORT Mutex {
41
    DISALLOW_COPY_AND_ASSIGN(Mutex);
42
public:
43
#if defined(OS_WIN)
44
  typedef CRITICAL_SECTION NativeHandle;
45
#elif defined(OS_POSIX)
46
  typedef pthread_mutex_t NativeHandle;
47
#endif
48
49
public:
50
10.2k
    Mutex() {
51
#if defined(OS_WIN)
52
    // The second parameter is the spin count, for short-held locks it avoid the
53
    // contending thread from going to sleep which helps performance greatly.
54
        ::InitializeCriticalSectionAndSpinCount(&_native_handle, 2000);
55
#elif defined(OS_POSIX)
56
10.2k
        pthread_mutex_init(&_native_handle, NULL);
57
10.2k
#endif
58
10.2k
    }
59
    
60
9.03k
    ~Mutex() {
61
#if defined(OS_WIN)
62
        ::DeleteCriticalSection(&_native_handle);
63
#elif defined(OS_POSIX)
64
        pthread_mutex_destroy(&_native_handle);
65
9.03k
#endif
66
9.03k
    }
67
68
    // Locks the mutex. If another thread has already locked the mutex, a call
69
    // to lock will block execution until the lock is acquired.
70
276
    void lock() {
71
#if defined(OS_WIN)
72
        ::EnterCriticalSection(&_native_handle);
73
#elif defined(OS_POSIX)
74
        pthread_mutex_lock(&_native_handle);
75
276
#endif
76
276
    }
77
78
    // Unlocks the mutex. The mutex must be locked by the current thread of
79
    // execution, otherwise, the behavior is undefined.
80
276
    void unlock() {
81
#if defined(OS_WIN)
82
        ::LeaveCriticalSection(&_native_handle);
83
#elif defined(OS_POSIX)
84
        pthread_mutex_unlock(&_native_handle);
85
276
#endif
86
276
    }
87
    
88
    // Tries to lock the mutex. Returns immediately.
89
    // On successful lock acquisition returns true, otherwise returns false.
90
0
    bool try_lock() {
91
0
#if defined(OS_WIN)
92
0
        return (::TryEnterCriticalSection(&_native_handle) != FALSE);
93
0
#elif defined(OS_POSIX)
94
0
        return pthread_mutex_trylock(&_native_handle) == 0;
95
0
#endif
96
0
    }
97
98
#if HAS_PTHREAD_MUTEX_TIMEDLOCK
99
0
    bool timed_lock(const struct timespec* abstime) {
100
0
        return pthread_mutex_timedlock(&_native_handle, abstime) == 0;
101
0
    }
102
#endif // HAS_PTHREAD_MUTEX_TIMEDLOCK
103
104
    // Returns the underlying implementation-defined native handle object.
105
0
    NativeHandle* native_handle() { return &_native_handle; }
106
107
private:
108
#if defined(OS_POSIX)
109
    // The posix implementation of ConditionVariable needs to be able
110
    // to see our lock and tweak our debugging counters, as it releases
111
    // and acquires locks inside of pthread_cond_{timed,}wait.
112
friend class ConditionVariable;
113
#elif defined(OS_WIN)
114
// The Windows Vista implementation of ConditionVariable needs the
115
// native handle of the critical section.
116
friend class WinVistaCondVar;
117
#endif
118
119
    NativeHandle _native_handle;
120
};
121
122
// TODO: Remove this type.
123
class BUTIL_EXPORT Lock : public Mutex {
124
    DISALLOW_COPY_AND_ASSIGN(Lock);
125
public:
126
1.06k
    Lock() {}
127
0
    ~Lock() {}
128
176
    void Acquire() { lock(); }
129
176
    void Release() { unlock(); }
130
0
    bool Try() { return try_lock(); }
131
176
    void AssertAcquired() const {}
132
};
133
134
// A helper class that acquires the given Lock while the AutoLock is in scope.
135
class AutoLock {
136
public:
137
    struct AlreadyAcquired {};
138
139
176
    explicit AutoLock(Lock& lock) : lock_(lock) {
140
176
        lock_.Acquire();
141
176
    }
142
143
0
    AutoLock(Lock& lock, const AlreadyAcquired&) : lock_(lock) {
144
0
        lock_.AssertAcquired();
145
0
    }
146
147
176
    ~AutoLock() {
148
176
        lock_.AssertAcquired();
149
176
        lock_.Release();
150
176
    }
151
152
private:
153
    Lock& lock_;
154
    DISALLOW_COPY_AND_ASSIGN(AutoLock);
155
};
156
157
// AutoUnlock is a helper that will Release() the |lock| argument in the
158
// constructor, and re-Acquire() it in the destructor.
159
class AutoUnlock {
160
public:
161
0
    explicit AutoUnlock(Lock& lock) : lock_(lock) {
162
0
        // We require our caller to have the lock.
163
0
        lock_.AssertAcquired();
164
0
        lock_.Release();
165
0
    }
166
167
0
    ~AutoUnlock() {
168
0
        lock_.Acquire();
169
0
    }
170
171
private:
172
    Lock& lock_;
173
    DISALLOW_COPY_AND_ASSIGN(AutoUnlock);
174
};
175
176
}  // namespace butil
177
178
#endif  // BUTIL_SYNCHRONIZATION_LOCK_H_