@@ -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 ) {
@@ -202,6 +248,19 @@ open class Thread : NSObject {
202
248
}
203
249
}
204
250
251
+ #if os(Windows)
252
+ open var stackSize : Int {
253
+ get {
254
+ var ulLowLimit : ULONG_PTR = 0
255
+ var ulHighLimit : ULONG_PTR = 0
256
+ GetCurrentThreadStackLimits ( & ulLowLimit, & ulHighLimit)
257
+ return Int ( ulLowLimit)
258
+ }
259
+ set {
260
+ _attr. dwThreadStackReservation = newValue
261
+ }
262
+ }
263
+ #else
205
264
open var stackSize : Int {
206
265
get {
207
266
var size : Int = 0
@@ -223,6 +282,7 @@ open class Thread : NSObject {
223
282
}
224
283
}
225
284
}
285
+ #endif
226
286
227
287
open var isExecuting : Bool {
228
288
return _status == . executing
@@ -252,6 +312,9 @@ open class Thread : NSObject {
252
312
defer { addrs. deallocate ( ) }
253
313
#if os(Android)
254
314
let count = 0
315
+ #elseif os(Windows)
316
+ let count = RtlCaptureStackBackTrace ( 0 , DWORD ( maxSupportedStackDepth) ,
317
+ addrs, nil )
255
318
#else
256
319
let count = backtrace ( addrs, Int32 ( maxSupportedStackDepth) )
257
320
#endif
@@ -270,6 +333,39 @@ open class Thread : NSObject {
270
333
open class var callStackSymbols : [ String ] {
271
334
#if os(Android)
272
335
return [ ]
336
+ #elseif os(Windows)
337
+ let hProcess : HANDLE = GetCurrentProcess ( )
338
+ SymSetOptions ( DWORD ( SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS) )
339
+ if SymInitializeW ( hProcess, nil , TRUE) == FALSE {
340
+ return [ ]
341
+ }
342
+ return backtraceAddresses { ( addresses, count) in
343
+ var symbols : [ String ] = [ ]
344
+
345
+ var buffer : UnsafeMutablePointer < Int8 > =
346
+ UnsafeMutablePointer< Int8>
347
+ . allocate( capacity: MemoryLayout < SYMBOL_INFO > . size + 128 )
348
+ defer { buffer. deallocate ( ) }
349
+
350
+ buffer. withMemoryRebound ( to: SYMBOL_INFO . self, capacity: 1 ) {
351
+ $0. pointee. SizeOfStruct = ULONG ( MemoryLayout< SYMBOL_INFO> . size)
352
+ $0. pointee. MaxNameLen = 128
353
+
354
+ var address = addresses
355
+ for _ in 1 ... count {
356
+ var dwDisplacement : DWORD64 = 0
357
+ if SymFromAddr ( hProcess, unsafeBitCast ( address. pointee,
358
+ to: DWORD64 . self) ,
359
+ & dwDisplacement, $0) == FALSE {
360
+ symbols. append ( " \( $0. pointee) " )
361
+ } else {
362
+ symbols. append ( String ( cString: & $0. pointee. Name) )
363
+ }
364
+ address = address. successor ( )
365
+ }
366
+ }
367
+ return symbols
368
+ }
273
369
#else
274
370
return backtraceAddresses ( { ( addrs, count) in
275
371
var symbols : [ String ] = [ ]
0 commit comments