98 lines
3.4 KiB
Swift
98 lines
3.4 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the SwiftNIO open source project
|
|
//
|
|
// Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors
|
|
// Licensed under Apache License v2.0
|
|
//
|
|
// See LICENSE.txt for license information
|
|
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#if os(Windows)
|
|
|
|
import WinSDK
|
|
|
|
|
|
typealias ThreadOpsSystem = ThreadOpsWindows
|
|
enum ThreadOpsWindows: ThreadOps {
|
|
typealias ThreadHandle = HANDLE
|
|
typealias ThreadSpecificKey = DWORD
|
|
typealias ThreadSpecificKeyDestructor = @convention(c) (UnsafeMutableRawPointer?) -> Void
|
|
|
|
static func threadName(_ thread: ThreadOpsSystem.ThreadHandle) -> String? {
|
|
var pszBuffer: PWSTR?
|
|
GetThreadDescription(thread, &pszBuffer)
|
|
guard let buffer = pszBuffer else { return nil }
|
|
let string: String = String(decodingCString: buffer, as: UTF16.self)
|
|
LocalFree(buffer)
|
|
return string
|
|
}
|
|
|
|
static func run(handle: inout ThreadOpsSystem.ThreadHandle?, args: Box<NIOThread.ThreadBoxValue>, detachThread: Bool) {
|
|
let argv0 = Unmanaged.passRetained(args).toOpaque()
|
|
|
|
// FIXME(compnerd) this should use the `stdcall` calling convention
|
|
let routine: @convention(c) (UnsafeMutableRawPointer?) -> CUnsignedInt = {
|
|
let boxed = Unmanaged<NIOThread.ThreadBox>.fromOpaque($0!).takeRetainedValue()
|
|
let (body, name) = (boxed.value.body, boxed.value.name)
|
|
let hThread: ThreadOpsSystem.ThreadHandle = GetCurrentThread()
|
|
|
|
if let name = name {
|
|
_ = name.withCString(encodedAs: UTF16.self) {
|
|
SetThreadDescription(hThread, $0)
|
|
}
|
|
}
|
|
|
|
body(NIOThread(handle: hThread, desiredName: name))
|
|
|
|
return 0
|
|
}
|
|
let hThread: HANDLE =
|
|
HANDLE(bitPattern: _beginthreadex(nil, 0, routine, argv0, 0, nil))!
|
|
|
|
if detachThread {
|
|
CloseHandle(hThread)
|
|
}
|
|
}
|
|
|
|
static func isCurrentThread(_ thread: ThreadOpsSystem.ThreadHandle) -> Bool {
|
|
return CompareObjectHandles(thread, GetCurrentThread())
|
|
}
|
|
|
|
static var currentThread: ThreadOpsSystem.ThreadHandle {
|
|
return GetCurrentThread()
|
|
}
|
|
|
|
static func joinThread(_ thread: ThreadOpsSystem.ThreadHandle) {
|
|
let dwResult: DWORD = WaitForSingleObject(thread, INFINITE)
|
|
assert(dwResult == WAIT_OBJECT_0, "WaitForSingleObject: \(GetLastError())")
|
|
}
|
|
|
|
static func allocateThreadSpecificValue(destructor: @escaping ThreadSpecificKeyDestructor) -> ThreadSpecificKey {
|
|
return FlsAlloc(destructor)
|
|
}
|
|
|
|
static func deallocateThreadSpecificValue(_ key: ThreadSpecificKey) {
|
|
let dwResult: Bool = FlsFree(key)
|
|
precondition(dwResult, "FlsFree: \(GetLastError())")
|
|
}
|
|
|
|
static func getThreadSpecificValue(_ key: ThreadSpecificKey) -> UnsafeMutableRawPointer? {
|
|
return FlsGetValue(key)
|
|
}
|
|
|
|
static func setThreadSpecificValue(key: ThreadSpecificKey, value: UnsafeMutableRawPointer?) {
|
|
FlsSetValue(key, value)
|
|
}
|
|
|
|
static func compareThreads(_ lhs: ThreadOpsSystem.ThreadHandle, _ rhs: ThreadOpsSystem.ThreadHandle) -> Bool {
|
|
return CompareObjectHandles(lhs, rhs)
|
|
}
|
|
}
|
|
|
|
#endif
|