@@ -38,7 +38,11 @@ private func NSThreadStart(_ context: UnsafeMutableRawPointer?) -> UnsafeMutable
38
38
let thread : Thread = NSObject . unretainedReference ( context!)
39
39
Thread . _currentThread. set ( thread)
40
40
if let name = thread. name {
41
+ #if os(Windows)
42
+ _CFThreadSetName ( GetCurrentThread ( ) , name)
43
+ #else
41
44
_CFThreadSetName ( pthread_self ( ) , name)
45
+ #endif
42
46
}
43
47
thread. _status = . executing
44
48
thread. main ( )
@@ -55,7 +59,11 @@ open class Thread : NSObject {
55
59
if Thread . isMainThread {
56
60
return mainThread
57
61
} else {
62
+ #if os(Windows)
63
+ return Thread ( thread: GetCurrentThread ( ) )
64
+ #else
58
65
return Thread ( thread: pthread_self ( ) )
66
+ #endif
59
67
}
60
68
}
61
69
}
@@ -89,6 +97,19 @@ open class Thread : NSObject {
89
97
}
90
98
91
99
open class func sleep( until date: Date ) {
100
+ #if os(Windows)
101
+ var hTimer : HANDLE = CreateWaitableTimerW ( nil , TRUE, nil )
102
+ // FIXME(compnerd) how to check that hTimer is not NULL?
103
+ defer { CloseHandle ( hTimer) }
104
+
105
+ // the timeout is in 100ns units
106
+ var liTimeout : LARGE_INTEGER =
107
+ LARGE_INTEGER ( QuadPart: LONGLONG ( date. timeIntervalSinceReferenceDate) * - 10000000 )
108
+ if SetWaitableTimer ( hTimer, & liTimeout, 0 , nil , nil , FALSE) == FALSE {
109
+ return
110
+ }
111
+ WaitForSingleObject ( hTimer, WinSDK . INFINITE)
112
+ #else
92
113
let start_ut = CFGetSystemUptime ( )
93
114
let start_at = CFAbsoluteTimeGetCurrent ( )
94
115
let end_at = date. timeIntervalSinceReferenceDate
@@ -109,9 +130,23 @@ open class Thread : NSObject {
109
130
}
110
131
ti = end_ut - CFGetSystemUptime( )
111
132
}
133
+ #endif
112
134
}
113
135
114
136
open class func sleep( forTimeInterval interval: TimeInterval ) {
137
+ #if os(Windows)
138
+ var hTimer : HANDLE = CreateWaitableTimerW ( nil , TRUE, nil )
139
+ // FIXME(compnerd) how to check that hTimer is not NULL?
140
+ defer { CloseHandle ( hTimer) }
141
+
142
+ // the timeout is in 100ns units
143
+ var liTimeout : LARGE_INTEGER =
144
+ LARGE_INTEGER ( QuadPart: LONGLONG ( interval) * - 10000000 )
145
+ if SetWaitableTimer ( hTimer, & liTimeout, 0 , nil , nil , FALSE) == FALSE {
146
+ return
147
+ }
148
+ WaitForSingleObject ( hTimer, WinSDK . INFINITE)
149
+ #else
115
150
var ti = interval
116
151
let start_ut = CFGetSystemUptime ( )
117
152
let end_ut = start_ut + ti
@@ -130,37 +165,48 @@ open class Thread : NSObject {
130
165
}
131
166
ti = end_ut - CFGetSystemUptime( )
132
167
}
168
+ #endif
133
169
}
134
170
135
171
open class func exit( ) {
136
172
Thread . current. _status = . finished
173
+ #if os(Windows)
174
+ ExitThread ( 0 )
175
+ #else
137
176
pthread_exit ( nil )
177
+ #endif
138
178
}
139
179
140
180
internal var _main : ( ) -> Void = { }
141
- private var _thread : pthread_t ? = nil
181
+ private var _thread : _CFThreadRef ? = nil
142
182
143
- #if CYGWIN
183
+ #if os(Windows) && !CYGWIN
184
+ internal var _attr : _CFThreadAttributes =
185
+ _CFThreadAttributes ( dwSizeOfAttributes: MemoryLayout< _CFThreadAttributes> . size,
186
+ dwThreadStackReservation: 0 )
187
+ #elseif CYGWIN
144
188
internal var _attr : pthread_attr_t ? = nil
145
189
#else
146
190
internal var _attr = pthread_attr_t ( )
147
191
#endif
148
192
internal var _status = _NSThreadStatus. initialized
149
193
internal var _cancelled = false
150
-
194
+
151
195
open private( set) var threadDictionary : NSMutableDictionary = NSMutableDictionary ( )
152
196
153
- internal init ( thread: pthread_t ) {
154
- // Note: even on Darwin this is a non-optional pthread_t ; this is only used for valid threads, which are never null pointers.
197
+ internal init ( thread: _CFThreadRef ) {
198
+ // Note: even on Darwin this is a non-optional _CFThreadRef ; this is only used for valid threads, which are never null pointers.
155
199
_thread = thread
156
200
}
157
201
158
202
public override init ( ) {
203
+ #if !os(Windows)
159
204
let _ = withUnsafeMutablePointer ( to: & _attr) { attr in
160
205
pthread_attr_init ( attr)
161
206
pthread_attr_setscope ( attr, Int32 ( PTHREAD_SCOPE_SYSTEM) )
162
207
pthread_attr_setdetachstate ( attr, Int32 ( PTHREAD_CREATE_DETACHED) )
163
208
}
209
+ #endif
164
210
}
165
211
166
212
public convenience init ( block: @escaping ( ) -> Swift . Void ) {
@@ -183,6 +229,10 @@ open class Thread : NSObject {
183
229
} else {
184
230
_thread = nil
185
231
}
232
+ #elseif os(Windows)
233
+ _thread = self . withRetainedReference {
234
+ return _CFThreadCreate ( _attr, NSThreadStart, $0)
235
+ }
186
236
#else
187
237
_thread = self . withRetainedReference {
188
238
return _CFThreadCreate ( self . _attr, NSThreadStart, $0)
@@ -202,6 +252,19 @@ open class Thread : NSObject {
202
252
}
203
253
}
204
254
255
+ #if os(Windows)
256
+ open var stackSize : Int {
257
+ get {
258
+ var ulLowLimit : ULONG_PTR = 0
259
+ var ulHighLimit : ULONG_PTR = 0
260
+ GetCurrentThreadStackLimits ( & ulLowLimit, & ulHighLimit)
261
+ return Int ( ulLowLimit)
262
+ }
263
+ set {
264
+ _attr. dwThreadStackReservation = newValue
265
+ }
266
+ }
267
+ #else
205
268
open var stackSize : Int {
206
269
get {
207
270
var size : Int = 0
@@ -223,6 +286,7 @@ open class Thread : NSObject {
223
286
}
224
287
}
225
288
}
289
+ #endif
226
290
227
291
open var isExecuting : Bool {
228
292
return _status == . executing
@@ -248,10 +312,13 @@ open class Thread : NSObject {
248
312
private class func backtraceAddresses< T> ( _ body: ( UnsafeMutablePointer < UnsafeMutableRawPointer ? > , Int ) -> [ T ] ) -> [ T ] {
249
313
// Same as swift/stdlib/public/runtime/Errors.cpp backtrace
250
314
let maxSupportedStackDepth = 128 ;
251
- let addrs = UnsafeMutablePointer< UnsafeMutableRawPointer?> . allocate( capacity: maxSupportedStackDepth)
315
+ var addrs = UnsafeMutablePointer< UnsafeMutableRawPointer?> . allocate( capacity: maxSupportedStackDepth)
252
316
defer { addrs. deallocate ( ) }
253
317
#if os(Android)
254
318
let count = 0
319
+ #elseif os(Windows)
320
+ let count = RtlCaptureStackBackTrace ( 0 , DWORD ( maxSupportedStackDepth) ,
321
+ addrs, nil )
255
322
#else
256
323
let count = backtrace ( addrs, Int32 ( maxSupportedStackDepth) )
257
324
#endif
@@ -270,6 +337,39 @@ open class Thread : NSObject {
270
337
open class var callStackSymbols : [ String ] {
271
338
#if os(Android)
272
339
return [ ]
340
+ #elseif os(Windows)
341
+ let hProcess : HANDLE = GetCurrentProcess ( )
342
+ SymSetOptions ( DWORD ( SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS) )
343
+ if SymInitializeW ( hProcess, nil , TRUE) == FALSE {
344
+ return [ ]
345
+ }
346
+ return backtraceAddresses { ( addresses, count) in
347
+ var symbols : [ String ] = [ ]
348
+
349
+ var buffer : UnsafeMutablePointer < Int8 > =
350
+ UnsafeMutablePointer< Int8>
351
+ . allocate( capacity: MemoryLayout < SYMBOL_INFO > . size + 128 )
352
+ defer { buffer. deallocate ( ) }
353
+
354
+ buffer. withMemoryRebound ( to: SYMBOL_INFO . self, capacity: 1 ) {
355
+ $0. pointee. SizeOfStruct = ULONG ( MemoryLayout< SYMBOL_INFO> . size)
356
+ $0. pointee. MaxNameLen = 128
357
+
358
+ var address = addresses
359
+ for _ in 1 ... count {
360
+ var dwDisplacement : DWORD64 = 0
361
+ if SymFromAddr ( hProcess, unsafeBitCast ( address. pointee,
362
+ to: DWORD64 . self) ,
363
+ & dwDisplacement, $0) == FALSE {
364
+ symbols. append ( " \( $0. pointee) " )
365
+ } else {
366
+ symbols. append ( String ( cString: & $0. pointee. Name) )
367
+ }
368
+ address = address. successor ( )
369
+ }
370
+ }
371
+ return symbols
372
+ }
273
373
#else
274
374
return backtraceAddresses ( { ( addrs, count) in
275
375
var symbols : [ String ] = [ ]
0 commit comments