Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 1
/* WARNING:  This file was automatically generated!
2
 * Original: ./src/thread/generic/SDL_syscond.c
3
 */
4
/*
5
    SDL - Simple DirectMedia Layer
6
    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
7
 
8
    This library is free software; you can redistribute it and/or
9
    modify it under the terms of the GNU Library General Public
10
    License as published by the Free Software Foundation; either
11
    version 2 of the License, or (at your option) any later version.
12
 
13
    This library 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 GNU
16
    Library General Public License for more details.
17
 
18
    You should have received a copy of the GNU Library General Public
19
    License along with this library; if not, write to the Free
20
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
 
22
    Sam Lantinga
23
    slouken@devolution.com
24
*/
25
 
26
 
27
/* An implementation of condition variables using semaphores and mutexes */
28
/*
29
   This implementation borrows heavily from the BeOS condition variable
30
   implementation, written by Christopher Tate and Owen Smith.  Thanks!
31
 */
32
 
33
#include 
34
#include 
35
 
36
#include "SDL_error.h"
37
#include "SDL_thread.h"
38
 
39
struct SDL_cond
40
{
41
	SDL_mutex *lock;
42
	int waiting;
43
	int signals;
44
	SDL_sem *wait_sem;
45
	SDL_sem *wait_done;
46
};
47
 
48
/* Create a condition variable */
49
SDL_cond * SDL_CreateCond(void)
50
{
51
	SDL_cond *cond;
52
 
53
	cond = (SDL_cond *) malloc(sizeof(SDL_cond));
54
	if ( cond ) {
55
		cond->lock = SDL_CreateMutex();
56
		cond->wait_sem = SDL_CreateSemaphore(0);
57
		cond->wait_done = SDL_CreateSemaphore(0);
58
		cond->waiting = cond->signals = 0;
59
		if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) {
60
			SDL_DestroyCond(cond);
61
			cond = NULL;
62
		}
63
	} else {
64
		SDL_OutOfMemory();
65
	}
66
	return(cond);
67
}
68
 
69
/* Destroy a condition variable */
70
void SDL_DestroyCond(SDL_cond *cond)
71
{
72
	if ( cond ) {
73
		if ( cond->wait_sem ) {
74
			SDL_DestroySemaphore(cond->wait_sem);
75
		}
76
		if ( cond->wait_done ) {
77
			SDL_DestroySemaphore(cond->wait_done);
78
		}
79
		if ( cond->lock ) {
80
			SDL_DestroyMutex(cond->lock);
81
		}
82
		free(cond);
83
	}
84
}
85
 
86
/* Restart one of the threads that are waiting on the condition variable */
87
int SDL_CondSignal(SDL_cond *cond)
88
{
89
	if ( ! cond ) {
90
		SDL_SetError("Passed a NULL condition variable");
91
		return -1;
92
	}
93
 
94
	/* If there are waiting threads not already signalled, then
95
	   signal the condition and wait for the thread to respond.
96
	*/
97
	SDL_LockMutex(cond->lock);
98
	if ( cond->waiting > cond->signals ) {
99
		++cond->signals;
100
		SDL_SemPost(cond->wait_sem);
101
		SDL_UnlockMutex(cond->lock);
102
		SDL_SemWait(cond->wait_done);
103
	} else {
104
		SDL_UnlockMutex(cond->lock);
105
	}
106
 
107
	return 0;
108
}
109
 
110
/* Restart all threads that are waiting on the condition variable */
111
int SDL_CondBroadcast(SDL_cond *cond)
112
{
113
	if ( ! cond ) {
114
		SDL_SetError("Passed a NULL condition variable");
115
		return -1;
116
	}
117
 
118
	/* If there are waiting threads not already signalled, then
119
	   signal the condition and wait for the thread to respond.
120
	*/
121
	SDL_LockMutex(cond->lock);
122
	if ( cond->waiting > cond->signals ) {
123
		int i, num_waiting;
124
 
125
		num_waiting = (cond->waiting - cond->signals);
126
		cond->signals = cond->waiting;
127
		for ( i=0; i
128
			SDL_SemPost(cond->wait_sem);
129
		}
130
		/* Now all released threads are blocked here, waiting for us.
131
		   Collect them all (and win fabulous prizes!) :-)
132
		 */
133
		SDL_UnlockMutex(cond->lock);
134
		for ( i=0; i
135
			SDL_SemWait(cond->wait_done);
136
		}
137
	} else {
138
		SDL_UnlockMutex(cond->lock);
139
	}
140
 
141
	return 0;
142
}
143
 
144
/* Wait on the condition variable for at most 'ms' milliseconds.
145
   The mutex must be locked before entering this function!
146
   The mutex is unlocked during the wait, and locked again after the wait.
147
 
148
Typical use:
149
 
150
Thread A:
151
	SDL_LockMutex(lock);
152
	while ( ! condition ) {
153
		SDL_CondWait(cond);
154
	}
155
	SDL_UnlockMutex(lock);
156
 
157
Thread B:
158
	SDL_LockMutex(lock);
159
	...
160
	condition = true;
161
	...
162
	SDL_UnlockMutex(lock);
163
 */
164
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
165
{
166
	int retval;
167
 
168
	if ( ! cond ) {
169
		SDL_SetError("Passed a NULL condition variable");
170
		return -1;
171
	}
172
 
173
	/* Obtain the protection mutex, and increment the number of waiters.
174
	   This allows the signal mechanism to only perform a signal if there
175
	   are waiting threads.
176
	 */
177
	SDL_LockMutex(cond->lock);
178
	++cond->waiting;
179
	SDL_UnlockMutex(cond->lock);
180
 
181
	/* Unlock the mutex, as is required by condition variable semantics */
182
	SDL_UnlockMutex(mutex);
183
 
184
	/* Wait for a signal */
185
	if ( ms == SDL_MUTEX_MAXWAIT ) {
186
		retval = SDL_SemWait(cond->wait_sem);
187
	} else {
188
		retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
189
	}
190
 
191
	/* Let the signaler know we have completed the wait, otherwise
192
           the signaler can race ahead and get the condition semaphore
193
           if we are stopped between the mutex unlock and semaphore wait,
194
           giving a deadlock.  See the following URL for details:
195
        http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
196
	*/
197
	SDL_LockMutex(cond->lock);
198
	if ( cond->signals > 0 ) {
199
		/* If we timed out, we need to eat a condition signal */
200
		if ( retval > 0 ) {
201
			SDL_SemWait(cond->wait_sem);
202
		}
203
		/* We always notify the signal thread that we are done */
204
		SDL_SemPost(cond->wait_done);
205
 
206
		/* Signal handshake complete */
207
		--cond->signals;
208
	}
209
	--cond->waiting;
210
	SDL_UnlockMutex(cond->lock);
211
 
212
	/* Lock the mutex, as is required by condition variable semantics */
213
	SDL_LockMutex(mutex);
214
 
215
	return retval;
216
}
217
 
218
/* Wait on the condition variable forever */
219
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
220
{
221
	return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
222
}