1/*
2    SDL - Simple DirectMedia Layer
3    Copyright (C) 1997-2012 Sam Lantinga
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19    Sam Lantinga
20    slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24/*
25 *	GNU pth conditions variables
26 *
27 *	Patrice Mandin
28 */
29
30#include <pth.h>
31
32#include "SDL_thread.h"
33#include "SDL_sysmutex_c.h"
34
35struct SDL_cond
36{
37	pth_cond_t	condpth_p;
38};
39
40/* Create a condition variable */
41SDL_cond * SDL_CreateCond(void)
42{
43	SDL_cond *cond;
44
45	cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
46	if ( cond ) {
47		if ( pth_cond_init(&(cond->condpth_p)) < 0 ) {
48			SDL_SetError("pthread_cond_init() failed");
49			SDL_free(cond);
50			cond = NULL;
51		}
52	} else {
53		SDL_OutOfMemory();
54	}
55	return(cond);
56}
57
58/* Destroy a condition variable */
59void SDL_DestroyCond(SDL_cond *cond)
60{
61	if ( cond ) {
62		SDL_free(cond);
63	}
64}
65
66/* Restart one of the threads that are waiting on the condition variable */
67int SDL_CondSignal(SDL_cond *cond)
68{
69	int retval;
70
71	if ( ! cond ) {
72		SDL_SetError("Passed a NULL condition variable");
73		return -1;
74	}
75
76	retval = 0;
77	if ( pth_cond_notify(&(cond->condpth_p), FALSE) != 0 ) {
78		SDL_SetError("pth_cond_notify() failed");
79		retval = -1;
80	}
81	return retval;
82}
83
84/* Restart all threads that are waiting on the condition variable */
85int SDL_CondBroadcast(SDL_cond *cond)
86{
87	int retval;
88
89	if ( ! cond ) {
90		SDL_SetError("Passed a NULL condition variable");
91		return -1;
92	}
93
94	retval = 0;
95	if ( pth_cond_notify(&(cond->condpth_p), TRUE) != 0 ) {
96		SDL_SetError("pth_cond_notify() failed");
97		retval = -1;
98	}
99	return retval;
100}
101
102/* Wait on the condition variable for at most 'ms' milliseconds.
103   The mutex must be locked before entering this function!
104   The mutex is unlocked during the wait, and locked again after the wait.
105
106Typical use:
107
108Thread A:
109	SDL_LockMutex(lock);
110	while ( ! condition ) {
111		SDL_CondWait(cond);
112	}
113	SDL_UnlockMutex(lock);
114
115Thread B:
116	SDL_LockMutex(lock);
117	...
118	condition = true;
119	...
120	SDL_UnlockMutex(lock);
121 */
122int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
123{
124	int retval;
125	pth_event_t ev;
126	int sec;
127
128	if ( ! cond ) {
129		SDL_SetError("Passed a NULL condition variable");
130		return -1;
131	}
132
133	retval = 0;
134
135	sec = ms/1000;
136	ev = pth_event(PTH_EVENT_TIME, pth_timeout(sec,(ms-sec*1000)*1000));
137
138	if ( pth_cond_await(&(cond->condpth_p), &(mutex->mutexpth_p), ev) != 0 ) {
139		SDL_SetError("pth_cond_await() failed");
140		retval = -1;
141	}
142
143    pth_event_free(ev, PTH_FREE_ALL);
144
145	return retval;
146}
147
148/* Wait on the condition variable forever */
149int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
150{
151	int retval;
152
153	if ( ! cond ) {
154		SDL_SetError("Passed a NULL condition variable");
155		return -1;
156	}
157
158	retval = 0;
159	if ( pth_cond_await(&(cond->condpth_p), &(mutex->mutexpth_p), NULL) != 0 ) {
160		SDL_SetError("pth_cond_await() failed");
161		retval = -1;
162	}
163	return retval;
164}
165