1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * 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
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef COMMON_COMPONENTS_PLATFORM_MUTEX_H
17 #define COMMON_COMPONENTS_PLATFORM_MUTEX_H
18
19 #include "common_interfaces/base/common.h"
20 #include "thread/thread_state_transition.h"
21
22 #ifdef DEBUG
23 #define FATAL_IF_ERROR(f, rc) \
24 do { \
25 if (rc != 0) { \
26 LOG_COMMON(FATAL)<< f << " failed: " << rc; \
27 } \
28 } while (false)
29 #else
30 #define FATAL_IF_ERROR(f, rc) static_cast<void>(0)
31 #endif
32
33 namespace common {
34 class Mutex {
35 public:
36 explicit Mutex(bool isInit = true);
37
38 ~Mutex();
39
40 void Lock();
41
42 bool TryLock();
43
44 void Unlock();
45
46 protected:
47 void Init(pthread_mutexattr_t *attrs);
48
49 private:
50 pthread_mutex_t mutex_;
51 friend class ConditionVariable;
52 };
53
Mutex(bool isInit)54 inline Mutex::Mutex(bool isInit) : mutex_()
55 {
56 if (isInit) {
57 Init(nullptr);
58 }
59 }
60
~Mutex()61 inline Mutex::~Mutex()
62 {
63 [[maybe_unused]] int rc = pthread_mutex_destroy(&mutex_);
64 FATAL_IF_ERROR("pthread_mutex_destroy", rc);
65 }
66
Init(pthread_mutexattr_t * attrs)67 inline void Mutex::Init(pthread_mutexattr_t *attrs)
68 {
69 [[maybe_unused]] int rc = pthread_mutex_init(&mutex_, attrs);
70 FATAL_IF_ERROR("pthread_mutex_init", rc);
71 }
72
Lock()73 inline void Mutex::Lock()
74 {
75 [[maybe_unused]] int rc = pthread_mutex_lock(&mutex_);
76 FATAL_IF_ERROR("pthread_mutex_lock", rc);
77 }
78
TryLock()79 inline bool Mutex::TryLock()
80 {
81 int rc = pthread_mutex_trylock(&mutex_);
82 if (rc == EBUSY) {
83 return false;
84 }
85
86 FATAL_IF_ERROR("pthread_mutex_trylock", rc);
87
88 return true;
89 }
90
Unlock()91 inline void Mutex::Unlock()
92 {
93 [[maybe_unused]] int rc = pthread_mutex_unlock(&mutex_);
94 FATAL_IF_ERROR("pthread_mutex_unlock", rc);
95 }
96
97 class LockHolder {
98 public:
LockHolder(Mutex & mtx)99 explicit LockHolder(Mutex &mtx) : lock_(mtx)
100 {
101 lock_.Lock();
102 }
103
~LockHolder()104 ~LockHolder()
105 {
106 lock_.Unlock();
107 }
108
109 private:
110 Mutex &lock_;
111
112 NO_COPY_SEMANTIC_CC(LockHolder);
113 NO_MOVE_SEMANTIC_CC(LockHolder);
114 };
115
116 class PUBLIC_API ConditionVariable {
117 public:
118 ConditionVariable();
119
120 ~ConditionVariable();
121
122 void Signal();
123
124 void SignalAll();
125
126 void Wait(Mutex *mutex);
127
128 bool TimedWait(Mutex *mutex, uint64_t ms, uint64_t ns = 0, bool is_absolute = false);
129
130 private:
131 pthread_cond_t cond_;
132 };
133
ConditionVariable()134 inline ConditionVariable::ConditionVariable() : cond_()
135 {
136 [[maybe_unused]]int rc = pthread_cond_init(&cond_, nullptr);
137 FATAL_IF_ERROR("pthread_cond_init", rc);
138 }
139
~ConditionVariable()140 inline ConditionVariable::~ConditionVariable()
141 {
142 [[maybe_unused]]int rc = pthread_cond_destroy(&cond_);
143 FATAL_IF_ERROR("pthread_cond_destroy", rc);
144 }
145
Signal()146 inline void ConditionVariable::Signal()
147 {
148 [[maybe_unused]]int rc = pthread_cond_signal(&cond_);
149 FATAL_IF_ERROR("pthread_cond_signal", rc);
150 }
151
SignalAll()152 inline void ConditionVariable::SignalAll()
153 {
154 [[maybe_unused]]int rc = pthread_cond_broadcast(&cond_);
155 FATAL_IF_ERROR("pthread_cond_broadcast", rc);
156 }
157
Wait(Mutex * mutex)158 inline void ConditionVariable::Wait(Mutex *mutex)
159 {
160 [[maybe_unused]]int rc = pthread_cond_wait(&cond_, &mutex->mutex_);
161 FATAL_IF_ERROR("pthread_cond_wait", rc);
162 }
163
164 }
165 #endif //COMMON_COMPONENTS_PLATFORM_MUTEX_H
166