Skip to content

Commit e1d7ee7

Browse files
committed
stdlib: implement ThreadBarriers in terms of Windows threading
1 parent 8b8198a commit e1d7ee7

File tree

1 file changed

+38
-1
lines changed

1 file changed

+38
-1
lines changed

stdlib/private/SwiftPrivateThreadExtras/ThreadBarriers.swift

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import Darwin
1616
import Glibc
1717
#elseif os(Windows)
1818
import MSVCRT
19+
import WinSDK
1920
#endif
2021

2122
//
@@ -29,7 +30,10 @@ public var _stdlib_THREAD_BARRIER_SERIAL_THREAD: CInt {
2930
}
3031

3132
public struct _stdlib_thread_barrier_t {
32-
#if os(Cygwin) || os(FreeBSD)
33+
#if os(Windows)
34+
var mutex: UnsafeMutablePointer<SRWLOCK>?
35+
var cond: UnsafeMutablePointer<CONDITION_VARIABLE>?
36+
#elseif os(Cygwin) || os(FreeBSD)
3337
var mutex: UnsafeMutablePointer<pthread_mutex_t?>?
3438
var cond: UnsafeMutablePointer<pthread_cond_t?>?
3539
#else
@@ -57,6 +61,13 @@ public func _stdlib_thread_barrier_init(
5761
errno = EINVAL
5862
return -1
5963
}
64+
#if os(Windows)
65+
barrier.pointee.mutex = UnsafeMutablePointer.allocate(capacity: 1)
66+
InitializeSRWLock(barrier.pointee.mutex!)
67+
68+
barrier.pointee.cond = UnsafeMutablePointer.allocate(capacity: 1)
69+
InitializeConditionVariable(barrier.pointee.cond!)
70+
#else
6071
barrier.pointee.mutex = UnsafeMutablePointer.allocate(capacity: 1)
6172
if pthread_mutex_init(barrier.pointee.mutex!, nil) != 0 {
6273
// FIXME: leaking memory.
@@ -67,13 +78,18 @@ public func _stdlib_thread_barrier_init(
6778
// FIXME: leaking memory, leaking a mutex.
6879
return -1
6980
}
81+
#endif
7082
barrier.pointee.count = count
7183
return 0
7284
}
7385

7486
public func _stdlib_thread_barrier_destroy(
7587
_ barrier: UnsafeMutablePointer<_stdlib_thread_barrier_t>
7688
) -> CInt {
89+
#if os(Windows)
90+
// Condition Variables do not need to be explicitly destroyed
91+
// Mutexes do not need to be explicitly destroyed
92+
#else
7793
if pthread_cond_destroy(barrier.pointee.cond!) != 0 {
7894
// FIXME: leaking memory, leaking a mutex.
7995
return -1
@@ -82,40 +98,61 @@ public func _stdlib_thread_barrier_destroy(
8298
// FIXME: leaking memory.
8399
return -1
84100
}
101+
#endif
85102
barrier.pointee.cond!.deinitialize(count: 1)
86103
barrier.pointee.cond!.deallocate()
104+
87105
barrier.pointee.mutex!.deinitialize(count: 1)
88106
barrier.pointee.mutex!.deallocate()
107+
89108
return 0
90109
}
91110

92111
public func _stdlib_thread_barrier_wait(
93112
_ barrier: UnsafeMutablePointer<_stdlib_thread_barrier_t>
94113
) -> CInt {
114+
#if os(Windows)
115+
AcquireSRWLockExclusive(barrier.pointee.mutex!)
116+
#else
95117
if pthread_mutex_lock(barrier.pointee.mutex!) != 0 {
96118
return -1
97119
}
120+
#endif
98121
barrier.pointee.numThreadsWaiting += 1
99122
if barrier.pointee.numThreadsWaiting < barrier.pointee.count {
100123
// Put the thread to sleep.
124+
#if os(Windows)
125+
// TODO(compnerd) modularize rpc.h to get INFIITE (0xffffffff)
126+
if SleepConditionVariableSRW(barrier.pointee.cond!, barrier.pointee.mutex!,
127+
0xffffffff, 0) == 0 {
128+
return -1
129+
}
130+
ReleaseSRWLockExclusive(barrier.pointee.mutex!)
131+
#else
101132
if pthread_cond_wait(barrier.pointee.cond!, barrier.pointee.mutex!) != 0 {
102133
return -1
103134
}
104135
if pthread_mutex_unlock(barrier.pointee.mutex!) != 0 {
105136
return -1
106137
}
138+
#endif
107139
return 0
108140
} else {
109141
// Reset thread count.
110142
barrier.pointee.numThreadsWaiting = 0
111143

112144
// Wake up all threads.
145+
#if os(Windows)
146+
WakeAllConditionVariable(barrier.pointee.cond!)
147+
ReleaseSRWLockExclusive(barrier.pointee.mutex!)
148+
#else
113149
if pthread_cond_broadcast(barrier.pointee.cond!) != 0 {
114150
return -1
115151
}
116152
if pthread_mutex_unlock(barrier.pointee.mutex!) != 0 {
117153
return -1
118154
}
155+
#endif
119156
return _stdlib_THREAD_BARRIER_SERIAL_THREAD
120157
}
121158
}

0 commit comments

Comments
 (0)