80 using native_handle_type = pthread_mutex_t *;
81 using type = MutexType;
82 using robustness = MutexRobustness;
86 pthread_mutexattr_t attr;
88 const auto attr_destroy = [](pthread_mutexattr_t * mutex_attr) {
90 const auto res_destroy = pthread_mutexattr_destroy(mutex_attr);
91 if (res_destroy != 0) {
92 throw std::system_error(
93 res_destroy, std::generic_category(),
"Failed to destroy mutex attribute");
96 using attr_cleanup_t = std::unique_ptr<pthread_mutexattr_t,
decltype(attr_destroy)>;
97 auto attr_cleanup = attr_cleanup_t(&attr, attr_destroy);
100 const auto res_attr = pthread_mutexattr_init(&attr);
102 throw std::system_error(
103 res_attr, std::system_category(),
"Failed to initialize mutex attribute");
107 const auto res_type = pthread_mutexattr_settype(&attr, MutexType::value);
110 throw std::system_error(res_type, std::system_category(),
"Failed to set mutex type");
114 const auto res_protocol = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
115 if (res_protocol != 0) {
116 throw std::system_error(res_protocol, std::system_category(),
"Failed to set mutex protocol");
122#if defined(__linux__)
123 const auto res_robust = pthread_mutexattr_setrobust(&attr, MutexRobustness::value);
124 if (res_robust != 0) {
125 throw std::system_error(res_robust, std::system_category(),
"Failed to set mutex robustness");
130 const auto res_init = pthread_mutex_init(&mutex_, &attr);
132 throw std::system_error(res_init, std::system_category(),
"Failed to initialize mutex");
138 const auto res = pthread_mutex_destroy(&mutex_);
140 std::cerr <<
"Failed to destroy mutex : " << std::strerror(res) << std::endl;
148 native_handle_type native_handle()
noexcept {
return &mutex_; }
152 const auto res = pthread_mutex_lock(&mutex_);
156 if (res == EOWNERDEAD) {
157#if defined(__linux__)
158 const auto res_consistent = pthread_mutex_consistent(&mutex_);
159 if (res_consistent != 0) {
160 throw std::runtime_error(
161 std::string(
"Failed to make mutex consistent : ") + std::strerror(res_consistent));
163 std::cerr <<
"Mutex owner died, but the mutex is consistent now. This shouldn't happen!"
168 <<
"Mutex owner died, but pthread_mutex_consistent is not supported on this platform."
171 }
else if (res == EDEADLK) {
172 throw std::system_error(res, std::system_category(),
"Deadlock detected");
174 throw std::runtime_error(std::string(
"Failed to lock mutex : ") + std::strerror(res));
178 void unlock()
noexcept
181 const auto res = pthread_mutex_unlock(&mutex_);
183 std::cerr <<
"Failed to unlock mutex : " << std::strerror(res) << std::endl;
189 const auto res = pthread_mutex_trylock(&mutex_);
195 }
else if (res == EOWNERDEAD) {
196#if defined(__linux__)
197 const auto res_consistent = pthread_mutex_consistent(&mutex_);
198 if (res_consistent != 0) {
199 throw std::runtime_error(
200 std::string(
"Failed to make mutex consistent : ") + std::strerror(res_consistent));
202 std::cerr <<
"Mutex owner died, but the mutex is consistent now. This shouldn't happen!"
206 <<
"Mutex owner died, but pthread_mutex_consistent is not supported on this platform."
209 }
else if (res == EDEADLK) {
210 throw std::system_error(res, std::system_category(),
"Deadlock detected");
212 throw std::runtime_error(std::string(
"Failed to try lock mutex : ") + std::strerror(res));
218 pthread_mutex_t mutex_;