source: rrlib_thread/tLock.h @ 0:c2492b69e880

Last change on this file since 0:c2492b69e880 was 0:c2492b69e880, checked in by Max Reichardt <mreichardt@…>, 7 years ago

Initial commit. These are refactored thread classes that were moved out of finroc_core_utils.

File size: 5.9 KB
Line 
1//
2// You received this file as part of RRLib
3// Robotics Research Library
4//
5// Copyright (C) Finroc GbR (finroc.org)
6//
7// This program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public License
9// as published by the Free Software Foundation; either version 2
10// of the License, or (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program; if not, write to the Free Software
19// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20//
21//----------------------------------------------------------------------
22/*!\file    rrlib/thread/tLock.h
23 *
24 * \author  Max Reichardt
25 *
26 * \date    2012-07-04
27 *
28 * \brief   Contains tLock
29 *
30 * \b tLock
31 *
32 * Lock for all mutex classes in rrlib_thread
33 *
34 */
35//----------------------------------------------------------------------
36#ifndef __rrlib__thread__tLock_h__
37#define __rrlib__thread__tLock_h__
38
39//----------------------------------------------------------------------
40// External includes (system with <>, local with "")
41//----------------------------------------------------------------------
42#include <mutex>
43
44//----------------------------------------------------------------------
45// Internal includes with ""
46//----------------------------------------------------------------------
47#include "rrlib/thread/tNoMutex.h"
48#include "rrlib/thread/tOrderedMutex.h"
49#include "rrlib/thread/tRecursiveMutex.h"
50#include "rrlib/thread/internal/tLockStack.h"
51
52//----------------------------------------------------------------------
53// Namespace declaration
54//----------------------------------------------------------------------
55namespace rrlib
56{
57namespace thread
58{
59
60//----------------------------------------------------------------------
61// Forward declarations / typedefs / enums
62//----------------------------------------------------------------------
63
64/*
65#ifndef _FINROC_SYSTEM_INSTALLATION_PRESENT_
66#ifndef NDEBUG
67#define RRLIB_THREAD_ENFORCE_LOCK_ORDER
68#endif
69#endif
70*/
71
72//----------------------------------------------------------------------
73// Class declaration
74//----------------------------------------------------------------------
75//! Lock
76/*!
77 * Lock for all mutex classes in rrlib_thread
78 */
79class tLock : boost::noncopyable
80{
81  friend class internal::tLockStack;
82
83//----------------------------------------------------------------------
84// Public methods and typedefs
85//----------------------------------------------------------------------
86public:
87
88#ifndef RRLIB_SINGLE_THREADED
89
90  explicit tLock(const tMutex& mutex) :
91    simple_lock(mutex.wrapped),
92    recursive_lock(),
93    locked_ordered(NULL),
94    locked_simple(&mutex)
95  {
96#ifdef RRLIB_THREAD_ENFORCE_LOCK_ORDER
97    internal::tLockStack::Push(this);
98#endif
99  }
100
101  explicit tLock(const tNoMutex& mutex) :
102    simple_lock(),
103    recursive_lock(),
104    locked_ordered(NULL),
105    locked_simple(NULL)
106  {
107  }
108
109  explicit tLock(const tOrderedMutex& mutex) :
110    simple_lock(mutex.wrapped),
111    recursive_lock(),
112    locked_ordered(&mutex),
113    locked_simple(&mutex)
114  {
115#ifdef RRLIB_THREAD_ENFORCE_LOCK_ORDER
116    internal::tLockStack::Push(this);
117#endif
118  }
119
120  explicit tLock(const tRecursiveMutex& mutex) :
121    simple_lock(),
122    recursive_lock(mutex.wrapped),
123    locked_ordered(&mutex),
124    locked_simple()
125  {
126#ifdef RRLIB_THREAD_ENFORCE_LOCK_ORDER
127    internal::tLockStack::Push(this);
128#endif
129  }
130
131  ~tLock()
132  {
133#ifdef RRLIB_THREAD_ENFORCE_LOCK_ORDER
134    if ((locked_simple && simple_lock.owns_lock()) || (locked_ordered && recursive_lock.owns_lock()))
135    {
136      bool ok = (internal::tLockStack::Pop() == this);
137      assert(ok);
138    }
139#endif
140  }
141
142  /*!
143   * \return Wrapped lock (only exists as long as this object!)
144   */
145  std::unique_lock<std::mutex>& GetSimpleLock()
146  {
147    return simple_lock;
148  }
149
150#else
151
152  template <typename T>
153  tLock(const T& mutex) {}
154
155  ~tLock() {}
156
157#endif
158
159  /*!
160   * \param mutex Mutex (either tOrderedMutex or tMutex)
161   *
162   * return Is specified mutex currently locked by this lock?
163   */
164  bool IsLocked(const tMutex& mutex) const
165  {
166    return &mutex == locked_simple && simple_lock.owns_lock();
167  }
168
169  /*!
170   * Unlock/Release lock
171   */
172  void Unlock()
173  {
174    if (simple_lock.owns_lock())
175    {
176#ifdef RRLIB_THREAD_ENFORCE_LOCK_ORDER
177      bool ok = (internal::tLockStack::Pop() == this);
178      assert(ok);
179#endif
180      simple_lock.unlock();
181    }
182    else if (recursive_lock.owns_lock())
183    {
184#ifdef RRLIB_THREAD_ENFORCE_LOCK_ORDER
185      bool ok = (internal::tLockStack::Pop() == this);
186      assert(ok);
187#endif
188      recursive_lock.unlock();
189    }
190  }
191
192  /*!
193   * Lock (again)
194   */
195  void Lock()
196  {
197    assert(((!simple_lock.owns_lock()) && (!(recursive_lock.owns_lock()))) && "Unlock before calling lock()");
198    if (locked_simple)
199    {
200#ifdef RRLIB_THREAD_ENFORCE_LOCK_ORDER
201      internal::tLockStack::Push(this);
202#endif
203      simple_lock.lock();
204    }
205    else if (locked_ordered)
206    {
207#ifdef RRLIB_THREAD_ENFORCE_LOCK_ORDER
208      internal::tLockStack::Push(this);
209#endif
210      recursive_lock.lock();
211    }
212  }
213
214//----------------------------------------------------------------------
215// Private fields and methods
216//----------------------------------------------------------------------
217private:
218
219#ifndef RRLIB_SINGLE_THREADED
220
221  /*! wrapped locks */
222  std::unique_lock<std::mutex> simple_lock;
223  std::unique_lock<std::recursive_mutex> recursive_lock;
224
225  /*! Raw pointer(s) to mutex that was acquired by this lock */
226  const tOrderedMutexBaseClass* locked_ordered;
227  const tMutex* locked_simple;
228
229#endif
230};
231
232//----------------------------------------------------------------------
233// End of namespace declaration
234//----------------------------------------------------------------------
235}
236}
237
238
239#endif
Note: See TracBrowser for help on using the repository browser.