/[svn]/linuxsampler/trunk/src/common/Mutex.h
ViewVC logotype

Contents of /linuxsampler/trunk/src/common/Mutex.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3290 - (show annotations) (download) (as text)
Fri Jun 23 12:24:58 2017 UTC (6 years, 11 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 6535 byte(s)
* Revised fundamental C++ classes "Thread", "Mutex" and
  "Condition" which fixes potential undefined behavior
  (note: this addresses mainly the POSIX implementation,
   Win32 is untested yet and would also need an update).
* Bumped version (2.0.0.svn64).

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2017 Christian Schoenebeck *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #ifndef __MUTEX_H__
25 #define __MUTEX_H__
26
27 #if defined(WIN32)
28 #include <windows.h>
29 #else
30 #include <pthread.h>
31 #endif
32
33 namespace LinuxSampler {
34
35 /** @brief Mutual exclusive objects
36 *
37 * This class provides the classical thread / process synchronisation
38 * technique called Mutex. It is used to protect critical sections, that is
39 * resources (typically data structures) from being used at the same time by
40 * different threads or processes which otherwise might turn into undefined
41 * and of course undesired behavior.
42 *
43 * Note: as this technique might block the calling thread and also implies
44 * a system call, this should not be used directly in realtime sensitive
45 * threads!
46 */
47 class Mutex {
48 public:
49 enum type_t {
50 RECURSIVE,
51 NON_RECURSIVE
52 };
53
54 /** @brief Constructor
55 *
56 * Creates a new Mutex object. The optional @a type argument defines
57 * the fundamental behavior of the Mutex object:
58 *
59 * - If @c RECURSIVE is passed (which is the default type) then the
60 * mutex will manage an additional lock count such that it allows the
61 * same thread to call Lock() multiple times; each time that thread
62 * calls Lock() the lock count will be increased by one, each time it
63 * calls Unlock() it will be decreased by one, and other threads will
64 * only be unblocked once the lock count fell to zero again.
65 *
66 * - If @c NON_RECURSIVE is passed then it is considered to be an error
67 * if the same thread calls Lock() while already owning the lock, and
68 * likewise it is considered to be an error if Unlock() is called if
69 * the calling thread hasn't locked the mutex.
70 *
71 * You should invest the required time to review your design in order to
72 * decide which mutex behavior fits to your design. Even though it might
73 * be tempting to stick with the lazy approach by using the @c RECURSIVE
74 * type, using the @c NON_RECURSIVE type does make sense if your design
75 * does not require a recursive mutex, because modern developer tools
76 * assist you spotting potential threading bugs in your code while using
77 * the @c NON_RECURSIVE type which can avoid developers' biggest fear of
78 * undefined behavior, plus also keep in mind that certain OS APIs are
79 * not compatible with recursive mutexes at all!
80 *
81 * @param type - optional: the fundamental behavior type for this mutex
82 * (default: @c RECURSIVE)
83 */
84 Mutex(type_t type = RECURSIVE);
85
86 /**
87 * Destructor
88 */
89 virtual ~Mutex();
90
91 /** @brief Lock this Mutex.
92 *
93 * If this Mutex object is currently be locked by another thread,
94 * then the calling thread will be blocked until the other thread
95 * unlocks this Mutex object. The calling thread though can safely
96 * call this method several times without danger to be blocked
97 * himself.
98 *
99 * The calling thread should call Unlock() as soon as the critical
100 * section was left.
101 */
102 void Lock();
103
104 /** @brief Try to lock this Mutex.
105 *
106 * Same as Lock() except that this method won't block the calling
107 * thread in case this Mutex object is currently locked by another
108 * thread. So this call will always immediately return and the
109 * return value has to be checked if the locking request was
110 * successful or not.
111 *
112 * @returns true if the Mutex object could be locked, false if the
113 * Mutex is currently locked by another thread
114 */
115 bool Trylock();
116
117 /** @brief Unlock this Mutex.
118 *
119 * If other threads are currently blocked and waiting due to a
120 * Lock() call, one of them will be awaken.
121 */
122 void Unlock();
123
124 protected:
125 #if defined(WIN32)
126 HANDLE hMutex;
127 #else
128 pthread_mutex_t __posix_mutex;
129 pthread_mutexattr_t __posix_mutexattr;
130 #endif
131 type_t type;
132 };
133
134 // Lock guard for exception safe locking
135 class LockGuard {
136 public:
137 LockGuard(Mutex& m) : pm(&m) {
138 m.Lock();
139 }
140
141 /**
142 * Empty LockGuard. This constructor can be used to implement conditional
143 * mutex protection like:
144 * @code
145 * Mutex m;
146 * LockGuard g;
147 * if (requiresMutexProtection()) g = LockGuard(m);
148 * @endcode
149 */
150 LockGuard() : pm(NULL) {
151 }
152
153 LockGuard(const LockGuard& g) : pm(g.pm) {
154 if (pm) pm->Lock();
155 }
156
157 ~LockGuard() {
158 if (pm) pm->Unlock();
159 }
160 private:
161 Mutex* pm;
162 };
163
164 } // namespace LinuxSampler
165
166 #endif // __MUTEX_H__

  ViewVC Help
Powered by ViewVC