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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3290 - (hide annotations) (download) (as text)
Fri Jun 23 12:24:58 2017 UTC (6 years, 10 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 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 3290 * Copyright (C) 2005 - 2017 Christian Schoenebeck *
7 schoenebeck 53 * *
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 senoner 1481 #if defined(WIN32)
28     #include <windows.h>
29     #else
30 schoenebeck 53 #include <pthread.h>
31 senoner 1481 #endif
32 schoenebeck 53
33 schoenebeck 880 namespace LinuxSampler {
34    
35 schoenebeck 550 /** @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 schoenebeck 53 class Mutex {
48     public:
49 schoenebeck 3290 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 schoenebeck 550 */
84 schoenebeck 3290 Mutex(type_t type = RECURSIVE);
85 schoenebeck 550
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 schoenebeck 53 void Lock();
103 schoenebeck 550
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 senkov 165 bool Trylock();
116 schoenebeck 550
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 schoenebeck 53 void Unlock();
123 persson 2427
124 schoenebeck 53 protected:
125 senoner 1481 #if defined(WIN32)
126 persson 2427 HANDLE hMutex;
127 senoner 1481 #else
128 schoenebeck 53 pthread_mutex_t __posix_mutex;
129     pthread_mutexattr_t __posix_mutexattr;
130 senoner 1481 #endif
131 schoenebeck 3290 type_t type;
132 schoenebeck 53 };
133    
134 persson 2427 // Lock guard for exception safe locking
135     class LockGuard {
136     public:
137 schoenebeck 2500 LockGuard(Mutex& m) : pm(&m) {
138 persson 2427 m.Lock();
139     }
140 schoenebeck 2500
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 schoenebeck 2501 LockGuard(const LockGuard& g) : pm(g.pm) {
154 schoenebeck 2500 if (pm) pm->Lock();
155     }
156    
157 persson 2427 ~LockGuard() {
158 schoenebeck 2500 if (pm) pm->Unlock();
159 persson 2427 }
160     private:
161 schoenebeck 2500 Mutex* pm;
162 persson 2427 };
163    
164 schoenebeck 880 } // namespace LinuxSampler
165    
166 schoenebeck 53 #endif // __MUTEX_H__

  ViewVC Help
Powered by ViewVC