• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2006 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 /* Semaphore functions using the Win32 API */
25 
26 #define WIN32_LEAN_AND_MEAN
27 #include <windows.h>
28 
29 #include "SDL_thread.h"
30 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
31 #include "win_ce_semaphore.h"
32 #endif
33 
34 
35 struct SDL_semaphore {
36 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
37 	SYNCHHANDLE id;
38 #else
39 	HANDLE id;
40 #endif
41 	Uint32 volatile count;
42 };
43 
44 
45 /* Create a semaphore */
SDL_CreateSemaphore(Uint32 initial_value)46 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
47 {
48 	SDL_sem *sem;
49 
50 	/* Allocate sem memory */
51 	sem = (SDL_sem *)SDL_malloc(sizeof(*sem));
52 	if ( sem ) {
53 		/* Create the semaphore, with max value 32K */
54 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
55 		sem->id = CreateSemaphoreCE(NULL, initial_value, 32*1024, NULL);
56 #else
57 		sem->id = CreateSemaphore(NULL, initial_value, 32*1024, NULL);
58 #endif
59 		sem->count = initial_value;
60 		if ( ! sem->id ) {
61 			SDL_SetError("Couldn't create semaphore");
62 			SDL_free(sem);
63 			sem = NULL;
64 		}
65 	} else {
66 		SDL_OutOfMemory();
67 	}
68 	return(sem);
69 }
70 
71 /* Free the semaphore */
SDL_DestroySemaphore(SDL_sem * sem)72 void SDL_DestroySemaphore(SDL_sem *sem)
73 {
74 	if ( sem ) {
75 		if ( sem->id ) {
76 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
77 			CloseSynchHandle(sem->id);
78 #else
79 			CloseHandle(sem->id);
80 #endif
81 			sem->id = 0;
82 		}
83 		SDL_free(sem);
84 	}
85 }
86 
SDL_SemWaitTimeout(SDL_sem * sem,Uint32 timeout)87 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
88 {
89 	int retval;
90 	DWORD dwMilliseconds;
91 
92 	if ( ! sem ) {
93 		SDL_SetError("Passed a NULL sem");
94 		return -1;
95 	}
96 
97 	if ( timeout == SDL_MUTEX_MAXWAIT ) {
98 		dwMilliseconds = INFINITE;
99 	} else {
100 		dwMilliseconds = (DWORD)timeout;
101 	}
102 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
103 	switch (WaitForSemaphoreCE(sem->id, dwMilliseconds)) {
104 #else
105 	switch (WaitForSingleObject(sem->id, dwMilliseconds)) {
106 #endif
107 	    case WAIT_OBJECT_0:
108 		--sem->count;
109 		retval = 0;
110 		break;
111 	    case WAIT_TIMEOUT:
112 		retval = SDL_MUTEX_TIMEDOUT;
113 		break;
114 	    default:
115 		SDL_SetError("WaitForSingleObject() failed");
116 		retval = -1;
117 		break;
118 	}
119 	return retval;
120 }
121 
122 int SDL_SemTryWait(SDL_sem *sem)
123 {
124 	return SDL_SemWaitTimeout(sem, 0);
125 }
126 
127 int SDL_SemWait(SDL_sem *sem)
128 {
129 	return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
130 }
131 
132 /* Returns the current count of the semaphore */
133 Uint32 SDL_SemValue(SDL_sem *sem)
134 {
135 	if ( ! sem ) {
136 		SDL_SetError("Passed a NULL sem");
137 		return 0;
138 	}
139 	return sem->count;
140 }
141 
142 int SDL_SemPost(SDL_sem *sem)
143 {
144 	if ( ! sem ) {
145 		SDL_SetError("Passed a NULL sem");
146 		return -1;
147 	}
148 	/* Increase the counter in the first place, because
149 	 * after a successful release the semaphore may
150 	 * immediately get destroyed by another thread which
151 	 * is waiting for this semaphore.
152 	 */
153 	++sem->count;
154 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
155 	if ( ReleaseSemaphoreCE(sem->id, 1, NULL) == FALSE ) {
156 #else
157 	if ( ReleaseSemaphore(sem->id, 1, NULL) == FALSE ) {
158 #endif
159 		--sem->count;	/* restore */
160 		SDL_SetError("ReleaseSemaphore() failed");
161 		return -1;
162 	}
163 	return 0;
164 }
165