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