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

Contents of /linuxsampler/trunk/src/common/Condition.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, 9 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 8711 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 __CONDITION_H__
25 #define __CONDITION_H__
26
27 #include "Mutex.h"
28
29 #if defined(WIN32)
30 #include <windows.h>
31 #endif
32
33 namespace LinuxSampler {
34
35 #if defined(WIN32)
36 class ConditionInternal;
37 #endif
38
39 /**
40 * Thread safe boolean condition.
41 *
42 * This is not meant to be used for real time operation!
43 */
44 class Condition : public Mutex {
45 public:
46 /** @brief Constructor
47 *
48 * Creates a new thread safe condition variable.
49 *
50 * Note that the default bahavior of the underlying mutex is
51 * @c NON_RECURSIVE by default, because in general if your design
52 * requires the Condition object's lock state to be recursive instead,
53 * then most probably this may result in dead locks or even undefined
54 * behavior, because the underlying OS API for conditions may not be
55 * compatible with recursive mutexes!
56 *
57 * @param bInitialCondition - optional: starting condition
58 * (default = false)
59 * @param mutexType - optional: fundamental behavior of underlying mutex
60 * (default: @c NON_RECURSIVE)
61 */
62 Condition(bool bInitialCondition = false, Mutex::type_t mutexType = Mutex::NON_RECURSIVE);
63
64 /**
65 * Destructor
66 */
67 virtual ~Condition();
68
69 /**
70 * Blocks the calling thread if current condition equals
71 * \a bCondition, in this case the calling thread will be blocked
72 * until condition turns. Upon successful return the Condition
73 * object is locked, so the calling thread can safely run it's
74 * critical section and has to explicitly call Unlock() right after
75 * it left it's critcal section.
76 *
77 * @e Note: If you don't provide a timeout value or if you provide a
78 * timeout value of exactly 0s and 0ns, then this call will block
79 * without any timeout, or in other words: @e infinity!
80 *
81 * @param bCondition - block in case of this condition
82 * @param TimeoutSeconds - optional: max. wait time in seconds
83 * (default: 0s)
84 * @param TimeoutNanoSeconds - optional: max wait time in nano
85 * seconds (default: 0ns)
86 * @returns 0 on success, a value less than 0 if timeout exceeded
87 */
88 int WaitIf(bool bCondition, long TimeoutSeconds = 0L, long TimeoutNanoSeconds = 0L);
89
90 /**
91 * Same as WaitIf(), except that WaitAndUnlockIf() will unlock the
92 * Condition object, so only use this call if you don't need to
93 * enter a thread critical section, otherwise use WaitIf() instead!
94 *
95 * @e Note: If you don't provide a timeout value or if you provide a
96 * timeout value of exactly 0s and 0ns, then this call will block
97 * without any timeout, or in other words: @e infinity!
98 *
99 * @param bCondition - block in case of this condition
100 * @param TimeoutSeconds - optional: max. wait time in seconds
101 * (default: 0s)
102 * @param TimeoutNanoSeconds - optional: max wait time in nano
103 * seconds (default: 0ns)
104 * @returns 0 on success, a value less than 0 if timeout exceeded
105 * @see WaitIf()
106 */
107 int WaitAndUnlockIf(bool bCondition, long TimeoutSeconds = 0L, long TimeoutNanoSeconds = 0L);
108
109 /**
110 * You should use this method instead of WaitIf() in case the calling
111 * thread already owns the Condition object's underlying mutex lock by
112 * previously calling Lock() before. Essentially the only difference to
113 * WaitIf() is that PreLockedWaitIf() does not call Lock() by itself.
114 */
115 int PreLockedWaitIf(bool bCondition, long TimeoutSeconds = 0L, long TimeoutNanoSeconds = 0L);
116
117 /**
118 * You should use this method instead of WaitAndUnlockIf() in case the
119 * calling thread already owns the Condition object's underlying mutex
120 * lock by previously calling Lock() before. Essentially the only
121 * difference to WaitAndUnlockIf() is that PreLockedWaitAndUnlockIf()
122 * does not call Lock() by itself.
123 */
124 int PreLockedWaitAndUnlockIf(bool bCondition, long TimeoutSeconds = 0L, long TimeoutNanoSeconds = 0L);
125
126 /**
127 * Set Condition object to \a bCondition. Upon change of the
128 * condition, other threads waiting for \a bCondition will be
129 * awakened. (Note the condition will not be locked for the calling
130 * thread after this method returns!)
131 *
132 * @param bCondition - new condition
133 */
134 void Set(bool bCondition);
135
136 /**
137 * You should use this method instead of Set() in case the calling
138 * thread already owns the Condition object's underlying mutex lock by
139 * previously calling Lock() before. Essentially the only difference to
140 * Set() is that PreLockedSet() does not call Lock() by itself.
141 */
142 void PreLockedSet(bool bCondition);
143
144 /**
145 * Returns the current boolean state of this condition object. This
146 * method never blocks, it returns immediately and doesn't use any
147 * system calls.
148 *
149 * @e Caution: this method is not thread safe! If you need to use
150 * the condition state in a thread critical context you must call
151 * @c Lock() and @c Unlock() respectively by yourself!
152 */
153 bool GetUnsafe();
154
155 #ifdef WIN32
156 /**
157 * Resets the condition. This is only needed on Windows, after
158 * a thread waiting for a condition has been stopped with
159 * StopThread.
160 */
161 void Reset();
162 #endif
163
164 protected:
165 int WaitIfInternal(bool bLock, bool bCondition, long TimeoutSeconds, long TimeoutNanoSeconds);
166 void SetInternal(bool bLock, bool bCondition);
167
168 #if defined(WIN32)
169 friend class ConditionInternal;
170 struct win32thread_cond_t {
171 int waiters_count_; ///< Number of waiting threads.
172 CRITICAL_SECTION waiters_count_lock_; ///< Serialize access to <waiters_count_>.
173 HANDLE sema_; ///< Semaphore used to queue up threads waiting for the condition to become signaled.
174 HANDLE waiters_done_; ///< An auto-reset event used by the broadcast/signal thread to wait for all the waiting thread(s) to wake up and be released from the semaphore.
175 size_t was_broadcast_; ///< Keeps track of whether we were broadcasting or signaling. This allows us to optimize the code if we're just signaling.
176 } __win32_true_condition, __win32_false_condition;
177 #else
178 pthread_cond_t __posix_true_condition;
179 pthread_cond_t __posix_false_condition;
180 #endif
181 bool bCondition;
182 };
183
184 } // namespace LinuxSampler
185
186 #endif // __CONDITION_H__

  ViewVC Help
Powered by ViewVC