Synchronization.h
Go to the documentation of this file.
1/*
2* This file is part of ArmarX.
3*
4* Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5*
6* ArmarX is free software; you can redistribute it and/or modify
7* it under the terms of the GNU General Public License version 2 as
8* published by the Free Software Foundation.
9*
10* ArmarX is distributed in the hope that it will be useful, but
11* WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program. If not, see <http://www.gnu.org/licenses/>.
17*
18* @package ArmarXCore::core
19* @author Jan Issac (jan dot issac at gmx dot de)
20* @date 2012
21* @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22* GNU General Public License
23*/
24
25#pragma once
26
27#include <boost/thread/condition_variable.hpp>
28#include <boost/thread/locks.hpp>
29#include <boost/thread/mutex.hpp>
30#include <boost/thread/recursive_mutex.hpp>
31#include <boost/thread/shared_mutex.hpp>
32
34
35#define MUTEX_TIMEOUT_MSEC 10000
36
38{
39 /**
40 * @struct MutexTimeoutException
41 * @ingroup Threads
42 * @brief The MutexTimeoutException struct
43 */
44 struct MutexTimeoutException : LocalException
45 {
46 MutexTimeoutException(int timeoutDelayMs, std::string mutexName = "")
47 {
48 std::stringstream reason;
49 reason << "A Thread failed to get a mutex '" + mutexName + "' after "
50 << timeoutDelayMs * 0.001 << " seconds!";
51 setReason(reason.str());
52 }
53
54 std::string
55 name() const override
56 {
57 return "armarx::exceptions::local::MutexTimeoutException";
58 }
59 };
60
61 struct MutexDestructionException : LocalException
62 {
63 MutexDestructionException(std::string mutexName = "") :
64 LocalException("A mutex '" + mutexName +
65 "' was not already unlocked in the destructor!")
66 {
67 }
68
69 std::string
70 name() const override
71 {
72 return "armarx::exceptions::local::MutexDestructionException";
73 }
74 };
75} // namespace armarx::exceptions::local
76
77namespace armarx
78{
79 /**
80 * @class HiddenTimedMutex
81 * @defgroup Threads
82 * @brief The HiddenTimedMutex class is a mutex, that has a normal boost::mutex
83 * interface, but will timeout after fixed (defined in MUTEX_TIMEOUT_MSEC)
84 * interval and throw a MutexTimeoutException, if it could not aquire the
85 * mutex in that time.<br/>
86 * This way, the stacktrace to the deadlock can be easily retrieved.
87 */
89 {
90 boost::timed_mutex timedMutex;
91 int timeoutDelayMs;
92 std::string mutexName;
93
94 public:
95 HiddenTimedMutex(int timeout = MUTEX_TIMEOUT_MSEC, std::string mutexName = "") :
96 timeoutDelayMs(timeout), mutexName(mutexName)
97 {
98 }
99
101 {
102 if (!try_lock())
103 {
104 // throw exceptions::local::MutexDestructionException();
105 std::cout << "A mutex ('" << mutexName
106 << "') was still locked in the destructor! Fix Application!\nBacktrace:\n"
107 << LocalException::generateBacktrace() << std::endl;
108 }
109 else
110 {
111 unlock();
112 }
113 }
114
115 void
117 {
118 boost::system_time timeout =
119 boost::get_system_time() + boost::posix_time::milliseconds(timeoutDelayMs);
120
121 if (!timedMutex.timed_lock(timeout))
122 {
123 throw exceptions::local::MutexTimeoutException(timeoutDelayMs, mutexName);
124 }
125 }
126
127 bool
129 {
130 return timedMutex.try_lock();
131 }
132
133 void
135 {
136 timedMutex.unlock();
137 }
138
139 using ScopedLock = boost::unique_lock<HiddenTimedMutex>;
140 using ScopedTryLock = boost::detail::try_lock_wrapper<HiddenTimedMutex>;
141 };
142
143 /**
144 \addtogroup Threads
145 @{
146 */
147
148
149 using Mutex = boost::mutex;
150 using ScopedLock = Mutex::scoped_lock;
151 using ScopedLockPtr = std::shared_ptr<ScopedLock>;
152 using ScopedTryLock = Mutex::scoped_try_lock;
153
154 using TimedMutex = boost::timed_mutex;
155 using ScopedTimedMutex = TimedMutex::scoped_lock;
156 using ScopedTimedMutexPtr = std::shared_ptr<ScopedTimedMutex>;
157 using ScopedTimedTryMutex = TimedMutex::scoped_try_lock;
158
159 using RecursiveMutex = boost::recursive_mutex;
160 using ScopedRecursiveLock = RecursiveMutex::scoped_lock;
161 using ScopedRecursiveLockPtr = std::shared_ptr<ScopedRecursiveLock>;
162 using ScopedRecursiveTryLock = RecursiveMutex::scoped_try_lock;
163
164 using TimedRecursiveMutex = boost::recursive_timed_mutex;
165 using ScopedTimedRecursiveLock = TimedRecursiveMutex::scoped_lock;
166 using ScopedTimedRecursiveLockPtr = std::shared_ptr<ScopedTimedRecursiveLock>;
167 using ScopedTimedRecursiveTryLock = TimedRecursiveMutex::scoped_try_lock;
168
169 using SharedMutex = boost::shared_mutex;
170
171 using ScopedUniqueLock = boost::unique_lock<boost::shared_mutex>;
172 using ScopedSharedLock = boost::shared_lock<boost::shared_mutex>;
173
174 using ScopedUniqueLockPtr = std::shared_ptr<ScopedUniqueLock>;
175 using ScopedSharedLockPtr = std::shared_ptr<ScopedSharedLock>;
176
177 using ConditionalVariable = boost::condition_variable;
178 /*
179 @}
180 */
181} // namespace armarx
#define MUTEX_TIMEOUT_MSEC
std::shared_ptr< ScopedLock > ScopedLockPtr
std::shared_ptr< ScopedTimedRecursiveLock > ScopedTimedRecursiveLockPtr
boost::condition_variable ConditionalVariable
boost::detail::try_lock_wrapper< HiddenTimedMutex > ScopedTryLock
boost::timed_mutex TimedMutex
RecursiveMutex::scoped_try_lock ScopedRecursiveTryLock
boost::shared_mutex SharedMutex
boost::mutex Mutex
HiddenTimedMutex(int timeout=MUTEX_TIMEOUT_MSEC, std::string mutexName="")
Mutex::scoped_lock ScopedLock
TimedMutex::scoped_try_lock ScopedTimedTryMutex
boost::recursive_mutex RecursiveMutex
TimedRecursiveMutex::scoped_lock ScopedTimedRecursiveLock
std::shared_ptr< ScopedSharedLock > ScopedSharedLockPtr
Mutex::scoped_try_lock ScopedTryLock
boost::unique_lock< HiddenTimedMutex > ScopedLock
boost::unique_lock< boost::shared_mutex > ScopedUniqueLock
boost::shared_lock< boost::shared_mutex > ScopedSharedLock
std::shared_ptr< ScopedTimedMutex > ScopedTimedMutexPtr
TimedMutex::scoped_lock ScopedTimedMutex
TimedRecursiveMutex::scoped_try_lock ScopedTimedRecursiveTryLock
RecursiveMutex::scoped_lock ScopedRecursiveLock
boost::recursive_timed_mutex TimedRecursiveMutex
std::shared_ptr< ScopedUniqueLock > ScopedUniqueLockPtr
std::shared_ptr< ScopedRecursiveLock > ScopedRecursiveLockPtr
This file offers overloads of toIce() and fromIce() functions for STL container types.
MutexTimeoutException(int timeoutDelayMs, std::string mutexName="")