diff --git a/Sources/ThreadLocal/ThreadLocal.swift b/Sources/ThreadLocal/ThreadLocal.swift index a669f22..9cd350b 100644 --- a/Sources/ThreadLocal/ThreadLocal.swift +++ b/Sources/ThreadLocal/ThreadLocal.swift @@ -18,7 +18,8 @@ import Darwin.C /// Manages a thread-local defined via the ``ThreadLocal()`` macro. /// -/// You do not use this type directly. Instead, your code interacts with thread-local variables by simply directly accessing them via their getter and setter. +/// You do not use this type directly. +/// Instead, your code interacts with thread-local variables by simply directly accessing them via their getter and setter. public final class ThreadLocal: Sendable { nonisolated(unsafe) public private(set) var _key: pthread_key_t public let _deallocator: Deallocator @@ -38,15 +39,16 @@ public final class ThreadLocal: Sendable { #if os(Linux) let destroyFn: @convention(c) (UnsafeMutableRawPointer?) -> Void = { ptr in if let ptr { - unsafeBitCast(ptr, to: Unmanaged.self).release() + Unmanaged.fromOpaque(ptr).release() } } #else let destroyFn: @convention(c) (UnsafeMutableRawPointer) -> Void = { ptr in - unsafeBitCast(ptr, to: Unmanaged.self).release() + Unmanaged.fromOpaque(ptr).release() } #endif - pthread_key_create(&_key, destroyFn) + let status = pthread_key_create(&_key, destroyFn) + precondition(status == 0, "pthread_key_create failed with status code \(status)") } @inlinable @@ -85,6 +87,10 @@ public final class ThreadLocal: Sendable { pthread_setspecific(_key, unmanaged.toOpaque()) } } + + deinit { + pthread_key_delete(_key) + } } diff --git a/Sources/ThreadLocalMacros/ThreadLocalMacro.swift b/Sources/ThreadLocalMacros/ThreadLocalMacro.swift index eef345c..edfb9ec 100644 --- a/Sources/ThreadLocalMacros/ThreadLocalMacro.swift +++ b/Sources/ThreadLocalMacros/ThreadLocalMacro.swift @@ -72,7 +72,7 @@ extension ThreadLocalMacro: PeerMacro { in context: some MacroExpansionContext ) throws -> [DeclSyntax] { guard let variableDeclaration = declaration.as(VariableDeclSyntax.self) else { - throw DiagnosticsError(syntax: declaration, message: "'@Property' can only be applied to a 'var' declaration", id: .invalidSyntax) + throw DiagnosticsError(syntax: declaration, message: "'@ThreadLocal' can only be applied to a 'var' declaration", id: .invalidSyntax) } guard variableDeclaration.isStatic else { // not reporting an error here bc the other function above is already taking care of that. @@ -82,14 +82,14 @@ extension ThreadLocalMacro: PeerMacro { variableDeclaration.bindings.count == 1 else { throw DiagnosticsError( syntax: declaration, - message: "'@Property' can only be applied to a 'var' declaration with a single binding", + message: "'@ThreadLocal' can only be applied to a 'var' declaration with a single binding", id: .invalidSyntax ) } guard let identifier = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier else { throw DiagnosticsError( syntax: declaration, - message: "'@Property' can only be applied to a 'var' declaration with a simple name", + message: "'@ThreadLocal' can only be applied to a 'var' declaration with a simple name", id: .invalidSyntax ) } diff --git a/Sources/ThreadLocalMacros/ThreadLocalMacros.swift b/Sources/ThreadLocalMacros/ThreadLocalMacros.swift index afd0963..5ee1269 100644 --- a/Sources/ThreadLocalMacros/ThreadLocalMacros.swift +++ b/Sources/ThreadLocalMacros/ThreadLocalMacros.swift @@ -11,6 +11,6 @@ import SwiftSyntaxMacros @main -struct SpeziSchedulerMacros: CompilerPlugin { +struct ThreadLocalMacros: CompilerPlugin { var providingMacros: [any Macro.Type] = [ThreadLocalMacro.self] }