17 #ifndef REALTIME_TOOLS__MUTEX_HPP_
18 #define REALTIME_TOOLS__MUTEX_HPP_
21 #error "The mutex.hpp header is not supported on Windows platforms"
45 static constexpr
int value = PTHREAD_MUTEX_ERRORCHECK;
50 static constexpr
int value = PTHREAD_MUTEX_RECURSIVE;
55 static constexpr
int value = PTHREAD_MUTEX_STALLED;
60 static constexpr
int value = PTHREAD_MUTEX_ROBUST;
68 template <
typename MutexType,
typename MutexRobustness>
72 using native_handle_type = pthread_mutex_t *;
73 using type = MutexType;
74 using robustness = MutexRobustness;
78 pthread_mutexattr_t attr;
80 const auto attr_destroy = [](pthread_mutexattr_t * mutex_attr) {
82 const auto res_destroy = pthread_mutexattr_destroy(mutex_attr);
83 if (res_destroy != 0) {
84 throw std::system_error(
85 res_destroy, std::generic_category(),
"Failed to destroy mutex attribute");
88 using attr_cleanup_t = std::unique_ptr<pthread_mutexattr_t, decltype(attr_destroy)>;
89 auto attr_cleanup = attr_cleanup_t(&attr, attr_destroy);
92 const auto res_attr = pthread_mutexattr_init(&attr);
94 throw std::system_error(
95 res_attr, std::system_category(),
"Failed to initialize mutex attribute");
99 const auto res_type = pthread_mutexattr_settype(&attr, MutexType::value);
102 throw std::system_error(res_type, std::system_category(),
"Failed to set mutex type");
106 const auto res_protocol = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
107 if (res_protocol != 0) {
108 throw std::system_error(res_protocol, std::system_category(),
"Failed to set mutex protocol");
112 const auto res_robust = pthread_mutexattr_setrobust(&attr, MutexRobustness::value);
113 if (res_robust != 0) {
114 throw std::system_error(res_robust, std::system_category(),
"Failed to set mutex robustness");
118 const auto res_init = pthread_mutex_init(&mutex_, &attr);
120 throw std::system_error(res_init, std::system_category(),
"Failed to initialize mutex");
126 const auto res = pthread_mutex_destroy(&mutex_);
128 std::cerr <<
"Failed to destroy mutex : " << std::strerror(res) << std::endl;
136 native_handle_type native_handle() noexcept {
return &mutex_; }
140 const auto res = pthread_mutex_lock(&mutex_);
144 if (res == EOWNERDEAD) {
145 const auto res_consistent = pthread_mutex_consistent(&mutex_);
146 if (res_consistent != 0) {
147 throw std::runtime_error(
148 std::string(
"Failed to make mutex consistent : ") + std::strerror(res_consistent));
150 std::cerr <<
"Mutex owner died, but the mutex is consistent now. This shouldn't happen!"
152 }
else if (res == EDEADLK) {
153 throw std::system_error(res, std::system_category(),
"Deadlock detected");
155 throw std::runtime_error(std::string(
"Failed to lock mutex : ") + std::strerror(res));
159 void unlock() noexcept
162 const auto res = pthread_mutex_unlock(&mutex_);
164 std::cerr <<
"Failed to unlock mutex : " << std::strerror(res) << std::endl;
170 const auto res = pthread_mutex_trylock(&mutex_);
176 }
else if (res == EOWNERDEAD) {
177 const auto res_consistent = pthread_mutex_consistent(&mutex_);
178 if (res_consistent != 0) {
179 throw std::runtime_error(
180 std::string(
"Failed to make mutex consistent : ") + std::strerror(res_consistent));
182 std::cerr <<
"Mutex owner died, but the mutex is consistent now. This shouldn't happen!"
184 }
else if (res == EDEADLK) {
185 throw std::system_error(res, std::system_category(),
"Deadlock detected");
187 throw std::runtime_error(std::string(
"Failed to try lock mutex : ") + std::strerror(res));
193 pthread_mutex_t mutex_;