1
- //===--- SwiftPrivatePthreadExtras .swift ----------------------------------===//
1
+ //===--- SwiftPrivateThreadExtras .swift ----------------------------------===//
2
2
//
3
3
// This source file is part of the Swift.org open source project
4
4
//
19
19
import Darwin
20
20
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku)
21
21
import Glibc
22
+ #elseif os(Windows)
23
+ import MSVCRT
24
+ import WinSDK
22
25
#endif
23
26
24
27
/// An abstract base class to encapsulate the context necessary to invoke
25
28
/// a block from pthread_create.
26
- internal class PthreadBlockContext {
29
+ internal class ThreadBlockContext {
27
30
/// Execute the block, and return an `UnsafeMutablePointer` to memory
28
31
/// allocated with `UnsafeMutablePointer.alloc` containing the result of the
29
32
/// block.
30
33
func run( ) -> UnsafeMutableRawPointer { fatalError ( " abstract " ) }
31
34
}
32
35
33
- internal class PthreadBlockContextImpl < Argument, Result> : PthreadBlockContext {
36
+ internal class ThreadBlockContextImpl < Argument, Result> : ThreadBlockContext {
34
37
let block : ( Argument ) -> Result
35
38
let arg : Argument
36
39
@@ -52,55 +55,82 @@ internal func invokeBlockContext(
52
55
_ contextAsVoidPointer: UnsafeMutableRawPointer ?
53
56
) -> UnsafeMutableRawPointer ! {
54
57
// The context is passed in +1; we're responsible for releasing it.
55
- let context = Unmanaged < PthreadBlockContext >
58
+ let context = Unmanaged < ThreadBlockContext >
56
59
. fromOpaque ( contextAsVoidPointer!)
57
60
. takeRetainedValue ( )
58
61
59
62
return context. run ( )
60
63
}
61
64
62
- #if os(Cygwin) || os(FreeBSD) || os(Haiku )
63
- public typealias _stdlib_pthread_attr_t = UnsafePointer < pthread_attr_t ? >
65
+ #if os(Windows )
66
+ public typealias ThreadHandle = HANDLE
64
67
#else
65
- public typealias _stdlib_pthread_attr_t = UnsafePointer < pthread_attr_t >
68
+ public typealias ThreadHandle = pthread_t
69
+
70
+ #if os(Linux) || os(Android)
71
+ internal func _make_pthread_t( ) -> pthread_t {
72
+ return pthread_t ( )
73
+ }
74
+ #else
75
+ internal func _make_pthread_t( ) -> pthread_t ? {
76
+ return nil
77
+ }
78
+ #endif
66
79
#endif
67
80
68
81
/// Block-based wrapper for `pthread_create`.
69
- public func _stdlib_pthread_create_block< Argument, Result> (
70
- _ attr: _stdlib_pthread_attr_t ? ,
82
+ public func _stdlib_thread_create_block< Argument, Result> (
71
83
_ start_routine: @escaping ( Argument ) -> Result ,
72
84
_ arg: Argument
73
- ) -> ( CInt , pthread_t ? ) {
74
- let context = PthreadBlockContextImpl ( block: start_routine, arg: arg)
85
+ ) -> ( CInt , ThreadHandle ? ) {
86
+ let context = ThreadBlockContextImpl ( block: start_routine, arg: arg)
75
87
// We hand ownership off to `invokeBlockContext` through its void context
76
88
// argument.
77
89
let contextAsVoidPointer = Unmanaged . passRetained ( context) . toOpaque ( )
78
90
91
+ #if os(Windows)
92
+ var threadID =
93
+ _beginthreadex ( nil , 0 , { invokeBlockContext ( $0) !
94
+ . assumingMemoryBound ( to: UInt32 . self) . pointee } ,
95
+ contextAsVoidPointer, 0 , nil )
96
+ if threadID == 0 {
97
+ return ( errno, nil )
98
+ } else {
99
+ return ( 0 , UnsafeMutablePointer < ThreadHandle > ( & threadID) . pointee)
100
+ }
101
+ #else
79
102
var threadID = _make_pthread_t ( )
80
- let result = pthread_create ( & threadID, attr ,
103
+ let result = pthread_create ( & threadID, nil ,
81
104
{ invokeBlockContext ( $0) } , contextAsVoidPointer)
82
105
if result == 0 {
83
106
return ( result, threadID)
84
107
} else {
85
108
return ( result, nil )
86
109
}
87
- }
88
-
89
- #if os(Linux) || os(Android)
90
- internal func _make_pthread_t( ) -> pthread_t {
91
- return pthread_t ( )
92
- }
93
- #else
94
- internal func _make_pthread_t( ) -> pthread_t ? {
95
- return nil
96
- }
97
110
#endif
111
+ }
98
112
99
113
/// Block-based wrapper for `pthread_join`.
100
- public func _stdlib_pthread_join < Result> (
101
- _ thread: pthread_t ,
114
+ public func _stdlib_thread_join < Result> (
115
+ _ thread: ThreadHandle ,
102
116
_ resultType: Result . Type
103
117
) -> ( CInt , Result ? ) {
118
+ #if os(Windows)
119
+ // TODO(compnerd) modularize rpc.h for INFINITE (0xffffffff)
120
+ let result = WaitForSingleObject ( thread, 0xffffffff ) ;
121
+ // TODO(compnerd) modularize WinBase.h for WAIT_OBJECT_0 (0)
122
+ if result == 0 {
123
+ let threadResult : DWORD = 0
124
+ GetExitCodeThread ( thread, & threadResult)
125
+ CloseHandle ( thread)
126
+
127
+ return ( result,
128
+ UnsafeMutablePointer < DWORD > ( & threadResult)
129
+ . withMemoryRebound ( to: Result . self, capacity: 1 ) { $0. pointee } )
130
+ } else {
131
+ return ( result, nil )
132
+ }
133
+ #else
104
134
var threadResultRawPtr : UnsafeMutableRawPointer ?
105
135
let result = pthread_join ( thread, & threadResultRawPtr)
106
136
if result == 0 {
@@ -113,36 +143,37 @@ public func _stdlib_pthread_join<Result>(
113
143
} else {
114
144
return ( result, nil )
115
145
}
146
+ #endif
116
147
}
117
148
118
149
public class _stdlib_Barrier {
119
- var _pthreadBarrier : _stdlib_pthread_barrier_t
150
+ var _threadBarrier : _stdlib_thread_barrier_t
120
151
121
- var _pthreadBarrierPtr : UnsafeMutablePointer < _stdlib_pthread_barrier_t > {
152
+ var _threadBarrierPtr : UnsafeMutablePointer < _stdlib_thread_barrier_t > {
122
153
return _getUnsafePointerToStoredProperties ( self )
123
- . assumingMemoryBound ( to: _stdlib_pthread_barrier_t . self)
154
+ . assumingMemoryBound ( to: _stdlib_thread_barrier_t . self)
124
155
}
125
156
126
157
public init ( threadCount: Int ) {
127
- self . _pthreadBarrier = _stdlib_pthread_barrier_t ( )
128
- let ret = _stdlib_pthread_barrier_init (
129
- _pthreadBarrierPtr , nil , CUnsignedInt ( threadCount) )
158
+ self . _threadBarrier = _stdlib_thread_barrier_t ( )
159
+ let ret = _stdlib_thread_barrier_init (
160
+ _threadBarrierPtr , CUnsignedInt ( threadCount) )
130
161
if ret != 0 {
131
- fatalError ( " _stdlib_pthread_barrier_init () failed" )
162
+ fatalError ( " _stdlib_thread_barrier_init () failed" )
132
163
}
133
164
}
134
165
135
166
deinit {
136
- let ret = _stdlib_pthread_barrier_destroy ( _pthreadBarrierPtr )
167
+ let ret = _stdlib_thread_barrier_destroy ( _threadBarrierPtr )
137
168
if ret != 0 {
138
- fatalError ( " _stdlib_pthread_barrier_destroy () failed" )
169
+ fatalError ( " _stdlib_thread_barrier_destroy () failed" )
139
170
}
140
171
}
141
172
142
173
public func wait( ) {
143
- let ret = _stdlib_pthread_barrier_wait ( _pthreadBarrierPtr )
144
- if !( ret == 0 || ret == _stdlib_PTHREAD_BARRIER_SERIAL_THREAD ) {
145
- fatalError ( " _stdlib_pthread_barrier_wait () failed" )
174
+ let ret = _stdlib_thread_barrier_wait ( _threadBarrierPtr )
175
+ if !( ret == 0 || ret == _stdlib_THREAD_BARRIER_SERIAL_THREAD ) {
176
+ fatalError ( " _stdlib_thread_barrier_wait () failed" )
146
177
}
147
178
}
148
179
}
0 commit comments