Skip to content

Commit 8a328a0

Browse files
committed
Merge 'mingw-modernize-pthread_cond_t'
This was pull request #1214 from rongjiecomputer/master Implement pthread_cond_t with Win32 CONDITION_VARIABLE Signed-off-by: Johannes Schindelin <[email protected]>
2 parents c28c558 + 3cb7263 commit 8a328a0

File tree

2 files changed

+7
-159
lines changed

2 files changed

+7
-159
lines changed

compat/win32/pthread.c

Lines changed: 0 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -56,141 +56,3 @@ pthread_t pthread_self(void)
5656
t.tid = GetCurrentThreadId();
5757
return t;
5858
}
59-
60-
int pthread_cond_init(pthread_cond_t *cond, const void *unused)
61-
{
62-
cond->waiters = 0;
63-
cond->was_broadcast = 0;
64-
InitializeCriticalSection(&cond->waiters_lock);
65-
66-
cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
67-
if (!cond->sema)
68-
die("CreateSemaphore() failed");
69-
70-
cond->continue_broadcast = CreateEvent(NULL, /* security */
71-
FALSE, /* auto-reset */
72-
FALSE, /* not signaled */
73-
NULL); /* name */
74-
if (!cond->continue_broadcast)
75-
die("CreateEvent() failed");
76-
77-
return 0;
78-
}
79-
80-
int pthread_cond_destroy(pthread_cond_t *cond)
81-
{
82-
CloseHandle(cond->sema);
83-
CloseHandle(cond->continue_broadcast);
84-
DeleteCriticalSection(&cond->waiters_lock);
85-
return 0;
86-
}
87-
88-
int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex)
89-
{
90-
int last_waiter;
91-
92-
EnterCriticalSection(&cond->waiters_lock);
93-
cond->waiters++;
94-
LeaveCriticalSection(&cond->waiters_lock);
95-
96-
/*
97-
* Unlock external mutex and wait for signal.
98-
* NOTE: we've held mutex locked long enough to increment
99-
* waiters count above, so there's no problem with
100-
* leaving mutex unlocked before we wait on semaphore.
101-
*/
102-
LeaveCriticalSection(mutex);
103-
104-
/* let's wait - ignore return value */
105-
WaitForSingleObject(cond->sema, INFINITE);
106-
107-
/*
108-
* Decrease waiters count. If we are the last waiter, then we must
109-
* notify the broadcasting thread that it can continue.
110-
* But if we continued due to cond_signal, we do not have to do that
111-
* because the signaling thread knows that only one waiter continued.
112-
*/
113-
EnterCriticalSection(&cond->waiters_lock);
114-
cond->waiters--;
115-
last_waiter = cond->was_broadcast && cond->waiters == 0;
116-
LeaveCriticalSection(&cond->waiters_lock);
117-
118-
if (last_waiter) {
119-
/*
120-
* cond_broadcast was issued while mutex was held. This means
121-
* that all other waiters have continued, but are contending
122-
* for the mutex at the end of this function because the
123-
* broadcasting thread did not leave cond_broadcast, yet.
124-
* (This is so that it can be sure that each waiter has
125-
* consumed exactly one slice of the semaphor.)
126-
* The last waiter must tell the broadcasting thread that it
127-
* can go on.
128-
*/
129-
SetEvent(cond->continue_broadcast);
130-
/*
131-
* Now we go on to contend with all other waiters for
132-
* the mutex. Auf in den Kampf!
133-
*/
134-
}
135-
/* lock external mutex again */
136-
EnterCriticalSection(mutex);
137-
138-
return 0;
139-
}
140-
141-
/*
142-
* IMPORTANT: This implementation requires that pthread_cond_signal
143-
* is called while the mutex is held that is used in the corresponding
144-
* pthread_cond_wait calls!
145-
*/
146-
int pthread_cond_signal(pthread_cond_t *cond)
147-
{
148-
int have_waiters;
149-
150-
EnterCriticalSection(&cond->waiters_lock);
151-
have_waiters = cond->waiters > 0;
152-
LeaveCriticalSection(&cond->waiters_lock);
153-
154-
/*
155-
* Signal only when there are waiters
156-
*/
157-
if (have_waiters)
158-
return ReleaseSemaphore(cond->sema, 1, NULL) ?
159-
0 : err_win_to_posix(GetLastError());
160-
else
161-
return 0;
162-
}
163-
164-
/*
165-
* DOUBLY IMPORTANT: This implementation requires that pthread_cond_broadcast
166-
* is called while the mutex is held that is used in the corresponding
167-
* pthread_cond_wait calls!
168-
*/
169-
int pthread_cond_broadcast(pthread_cond_t *cond)
170-
{
171-
EnterCriticalSection(&cond->waiters_lock);
172-
173-
if ((cond->was_broadcast = cond->waiters > 0)) {
174-
/* wake up all waiters */
175-
ReleaseSemaphore(cond->sema, cond->waiters, NULL);
176-
LeaveCriticalSection(&cond->waiters_lock);
177-
/*
178-
* At this point all waiters continue. Each one takes its
179-
* slice of the semaphor. Now it's our turn to wait: Since
180-
* the external mutex is held, no thread can leave cond_wait,
181-
* yet. For this reason, we can be sure that no thread gets
182-
* a chance to eat *more* than one slice. OTOH, it means
183-
* that the last waiter must send us a wake-up.
184-
*/
185-
WaitForSingleObject(cond->continue_broadcast, INFINITE);
186-
/*
187-
* Since the external mutex is held, no thread can enter
188-
* cond_wait, and, hence, it is safe to reset this flag
189-
* without cond->waiters_lock held.
190-
*/
191-
cond->was_broadcast = 0;
192-
} else {
193-
LeaveCriticalSection(&cond->waiters_lock);
194-
}
195-
return 0;
196-
}

compat/win32/pthread.h

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -32,27 +32,13 @@ typedef int pthread_mutexattr_t;
3232
#define pthread_mutexattr_settype(a, t) 0
3333
#define PTHREAD_MUTEX_RECURSIVE 0
3434

35-
/*
36-
* Implement simple condition variable for Windows threads, based on ACE
37-
* implementation.
38-
*
39-
* See original implementation: http://bit.ly/1vkDjo
40-
* ACE homepage: http://www.cse.wustl.edu/~schmidt/ACE.html
41-
* See also: http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
42-
*/
43-
typedef struct {
44-
LONG waiters;
45-
int was_broadcast;
46-
CRITICAL_SECTION waiters_lock;
47-
HANDLE sema;
48-
HANDLE continue_broadcast;
49-
} pthread_cond_t;
50-
51-
extern int pthread_cond_init(pthread_cond_t *cond, const void *unused);
52-
extern int pthread_cond_destroy(pthread_cond_t *cond);
53-
extern int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex);
54-
extern int pthread_cond_signal(pthread_cond_t *cond);
55-
extern int pthread_cond_broadcast(pthread_cond_t *cond);
35+
#define pthread_cond_t CONDITION_VARIABLE
36+
37+
#define pthread_cond_init(a,b) InitializeConditionVariable((a))
38+
#define pthread_cond_destroy(a) do {} while (0)
39+
#define pthread_cond_wait(a,b) return_0(SleepConditionVariableCS((a), (b), INFINITE))
40+
#define pthread_cond_signal WakeConditionVariable
41+
#define pthread_cond_broadcast WakeAllConditionVariable
5642

5743
/*
5844
* Simple thread creation implementation using pthread API

0 commit comments

Comments
 (0)