Skip to content

Commit 2bf28cb

Browse files
committed
Updates to Swift-Log v1.4.4 and adds Sendable support throughout
1 parent 8731970 commit 2bf28cb

File tree

6 files changed

+398
-127
lines changed

6 files changed

+398
-127
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version:5.3
1+
// swift-tools-version:5.5
22
// The swift-tools-version declares the minimum version of Swift required to build this package.
33

44
import PackageDescription

Sources/Logging/Interpolation.swift

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
import CoreGraphics
22

3-
@frozen public struct LogInterpolation: StringInterpolationProtocol {
3+
@frozen public struct LogInterpolation: StringInterpolationProtocol, Sendable {
44

5-
@usableFromInline enum Value {
5+
@usableFromInline enum Value: Sendable {
66
case literal(String)
7-
case string(() -> String, alignment: LogStringAlignment, privacy: LogPrivacy)
8-
case convertible(() -> CustomStringConvertible, alignment: LogStringAlignment, privacy: LogPrivacy)
9-
case signedInt(() -> Int64, format: LogIntegerFormatting, alignment: LogStringAlignment, privacy: LogPrivacy)
10-
case unsignedInt(() -> UInt64, format: LogIntegerFormatting, alignment: LogStringAlignment, privacy: LogPrivacy)
11-
case float(() -> Float, format: LogFloatFormatting, alignment: LogStringAlignment, privacy: LogPrivacy)
12-
case cgfloat(() -> CGFloat, format: LogFloatFormatting, alignment: LogStringAlignment, privacy: LogPrivacy)
13-
case double(() -> Double, format: LogFloatFormatting, alignment: LogStringAlignment, privacy: LogPrivacy)
14-
case bool(() -> Bool, format: LogBoolFormat, privacy: LogPrivacy)
15-
case object(() -> NSObject, privacy: LogPrivacy)
16-
case meta(() -> Any.Type, alignment: LogStringAlignment, privacy: LogPrivacy)
7+
case string(@Sendable () -> String, alignment: LogStringAlignment, privacy: LogPrivacy)
8+
case convertible(@Sendable () -> CustomStringConvertible, alignment: LogStringAlignment, privacy: LogPrivacy)
9+
case signedInt(@Sendable () -> Int64, format: LogIntegerFormatting, alignment: LogStringAlignment, privacy: LogPrivacy)
10+
case unsignedInt(@Sendable () -> UInt64, format: LogIntegerFormatting, alignment: LogStringAlignment, privacy: LogPrivacy)
11+
case float(@Sendable () -> Float, format: LogFloatFormatting, alignment: LogStringAlignment, privacy: LogPrivacy)
12+
case cgfloat(@Sendable () -> CGFloat, format: LogFloatFormatting, alignment: LogStringAlignment, privacy: LogPrivacy)
13+
case double(@Sendable () -> Double, format: LogFloatFormatting, alignment: LogStringAlignment, privacy: LogPrivacy)
14+
case bool(@Sendable () -> Bool, format: LogBoolFormat, privacy: LogPrivacy)
15+
case object(@Sendable () -> NSObject, privacy: LogPrivacy)
16+
case meta(@Sendable () -> Any.Type, alignment: LogStringAlignment, privacy: LogPrivacy)
1717
}
1818

1919
private(set) var storage: [Value] = []
@@ -28,77 +28,77 @@ import CoreGraphics
2828

2929
extension LogInterpolation {
3030
/// Defines interpolation for expressions of type String.
31-
public mutating func appendInterpolation(_ argumentString: @autoclosure @escaping () -> String, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
31+
public mutating func appendInterpolation(_ argumentString: @Sendable @autoclosure @escaping () -> String, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
3232
storage.append(.string(argumentString, alignment: align, privacy: privacy))
3333
}
3434

3535
/// Defines interpolation for values conforming to CustomStringConvertible. The values
3636
/// are displayed using the description methods on them.
37-
public mutating func appendInterpolation<T>(_ value: @autoclosure @escaping () -> T, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) where T: CustomStringConvertible {
37+
public mutating func appendInterpolation<T>(_ value: @Sendable @autoclosure @escaping () -> T, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) where T: CustomStringConvertible {
3838
storage.append(.convertible(value, alignment: align, privacy: privacy))
3939
}
4040
}
4141

4242
extension LogInterpolation {
4343
/// Defines interpolation for meta-types.
44-
public mutating func appendInterpolation(_ value: @autoclosure @escaping () -> Any.Type, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
44+
public mutating func appendInterpolation(_ value: @Sendable @autoclosure @escaping () -> Any.Type, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
4545
storage.append(.meta(value, alignment: align, privacy: privacy))
4646
}
4747

4848
/// Defines interpolation for expressions of type NSObject.
49-
public mutating func appendInterpolation(_ argumentObject: @autoclosure @escaping () -> NSObject, privacy: LogPrivacy = .private) {
49+
public mutating func appendInterpolation(_ argumentObject: @Sendable @autoclosure @escaping () -> NSObject, privacy: LogPrivacy = .private) {
5050
storage.append(.object(argumentObject, privacy: privacy))
5151
}
5252
}
5353

5454
extension LogInterpolation {
5555
/// Defines interpolation for expressions of type Int
56-
public mutating func appendInterpolation<T: SignedInteger>(_ number: @autoclosure @escaping () -> T, format: LogIntegerFormatting = .decimal, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
56+
public mutating func appendInterpolation<T: SignedInteger>(_ number: @Sendable @autoclosure @escaping () -> T, format: LogIntegerFormatting = .decimal, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
5757
storage.append(.signedInt({ Int64(number()) }, format: format, alignment: align, privacy: privacy))
5858
}
5959

6060
/// Defines interpolation for expressions of type UInt
61-
public mutating func appendInterpolation<T: UnsignedInteger>(_ number: @autoclosure @escaping () -> T, format: LogIntegerFormatting = .decimal, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
61+
public mutating func appendInterpolation<T: UnsignedInteger>(_ number: @Sendable @autoclosure @escaping () -> T, format: LogIntegerFormatting = .decimal, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
6262
storage.append(.unsignedInt({ UInt64(number()) }, format: format, alignment: align, privacy: privacy))
6363
}
6464
}
6565

6666
extension LogInterpolation {
6767
/// Defines interpolation for expressions of type Float
68-
public mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Float, format: LogFloatFormatting = .fixed, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
68+
public mutating func appendInterpolation(_ number: @Sendable @autoclosure @escaping () -> Float, format: LogFloatFormatting = .fixed, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
6969
storage.append(.float(number, format: format, alignment: align, privacy: privacy))
7070
}
7171

7272
/// Defines interpolation for expressions of type CGFloat
73-
public mutating func appendInterpolation(_ number: @autoclosure @escaping () -> CGFloat, format: LogFloatFormatting = .fixed, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
73+
public mutating func appendInterpolation(_ number: @Sendable @autoclosure @escaping () -> CGFloat, format: LogFloatFormatting = .fixed, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
7474
storage.append(.cgfloat(number, format: format, alignment: align, privacy: privacy))
7575
}
7676

7777
/// Defines interpolation for expressions of type Double
78-
public mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Double, format: LogFloatFormatting = .fixed, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
78+
public mutating func appendInterpolation(_ number: @Sendable @autoclosure @escaping () -> Double, format: LogFloatFormatting = .fixed, align: LogStringAlignment = .none, privacy: LogPrivacy = .private) {
7979
storage.append(.double(number, format: format, alignment: align, privacy: privacy))
8080
}
8181
}
8282

8383
extension LogInterpolation {
8484
/// Defines interpolation for expressions of type Bool
85-
public mutating func appendInterpolation(_ boolean: @autoclosure @escaping () -> Bool, format: LogBoolFormat = .truth, privacy: LogPrivacy = .private) {
85+
public mutating func appendInterpolation(_ boolean: @Sendable @autoclosure @escaping () -> Bool, format: LogBoolFormat = .truth, privacy: LogPrivacy = .private) {
8686
storage.append(.bool(boolean, format: format, privacy: privacy))
8787
}
8888
}
8989

90-
public enum LogBoolFormat {
90+
public enum LogBoolFormat: Sendable {
9191
/// Displays an interpolated boolean value as true or false.
9292
case truth
9393
/// Displays an interpolated boolean value as yes or no.
9494
case answer
9595
}
9696

97-
public struct LogStringAlignment {
98-
enum Alignment {
97+
public struct LogStringAlignment: Sendable {
98+
enum Alignment: Sendable {
9999
case none
100-
case left(columns: () -> Int)
101-
case right(columns: () -> Int)
100+
case left(columns: @Sendable () -> Int)
101+
case right(columns: @Sendable () -> Int)
102102
}
103103

104104
let alignment: Alignment
@@ -107,18 +107,18 @@ public struct LogStringAlignment {
107107
LogStringAlignment(alignment: .none)
108108
}
109109

110-
public static func right(columns: @autoclosure @escaping () -> Int) -> LogStringAlignment {
110+
public static func right(columns: @Sendable @autoclosure @escaping () -> Int) -> LogStringAlignment {
111111
LogStringAlignment(alignment: .right(columns: columns))
112112
}
113113

114-
public static func left(columns: @autoclosure @escaping () -> Int) -> LogStringAlignment {
114+
public static func left(columns: @Sendable @autoclosure @escaping () -> Int) -> LogStringAlignment {
115115
LogStringAlignment(alignment: .left(columns: columns))
116116
}
117117
}
118118

119-
public struct LogFloatFormatting {
120-
enum Format {
121-
case fixed(precision: () -> Int, explicitPositiveSign: Bool)
119+
public struct LogFloatFormatting: Sendable {
120+
enum Format: Sendable {
121+
case fixed(precision: @Sendable () -> Int, explicitPositiveSign: Bool)
122122
}
123123

124124
let format: Format
@@ -131,14 +131,14 @@ public struct LogFloatFormatting {
131131
fixed(precision: 6, explicitPositiveSign: explicitPositiveSign)
132132
}
133133

134-
public static func fixed(precision: @autoclosure @escaping () -> Int, explicitPositiveSign: Bool = false) -> LogFloatFormatting {
134+
public static func fixed(precision: @Sendable @autoclosure @escaping () -> Int, explicitPositiveSign: Bool = false) -> LogFloatFormatting {
135135
LogFloatFormatting(format: .fixed(precision: precision, explicitPositiveSign: explicitPositiveSign))
136136
}
137137
}
138138

139-
public struct LogIntegerFormatting {
139+
public struct LogIntegerFormatting: Sendable {
140140
enum Format {
141-
case decimal(minDigits: () -> Int, explicitPositiveSign: Bool)
141+
case decimal(minDigits: @Sendable () -> Int, explicitPositiveSign: Bool)
142142
}
143143

144144
let format: Format
@@ -151,13 +151,13 @@ public struct LogIntegerFormatting {
151151
decimal(explicitPositiveSign: explicitPositiveSign, minDigits: 0)
152152
}
153153

154-
public static func decimal(explicitPositiveSign: Bool = false, minDigits: @autoclosure @escaping () -> Int) -> LogIntegerFormatting {
154+
public static func decimal(explicitPositiveSign: Bool = false, minDigits: @Sendable @autoclosure @escaping () -> Int) -> LogIntegerFormatting {
155155
LogIntegerFormatting(format: .decimal(minDigits: minDigits, explicitPositiveSign: explicitPositiveSign))
156156
}
157157
}
158158

159-
@frozen public struct LogPrivacy: Equatable {
160-
public enum Mask: Equatable {
159+
@frozen public struct LogPrivacy: Equatable, Sendable {
160+
public enum Mask: Equatable, Sendable {
161161
case hash
162162
case none
163163
}

Sources/Logging/Locks.swift

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@
2828

2929
#if canImport(WASILibc)
3030
// No locking on WASILibc
31-
#else
32-
33-
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
31+
#elseif canImport(Darwin)
3432
import Darwin
3533
#elseif os(Windows)
3634
import WinSDK
@@ -138,7 +136,9 @@ extension Lock {
138136
/// one used by NIO. On Windows, the lock is based on the substantially similar
139137
/// `SRWLOCK` type.
140138
internal final class ReadWriteLock {
141-
#if os(Windows)
139+
#if canImport(WASILibc)
140+
// WASILibc is single threaded, provides no locks
141+
#elseif os(Windows)
142142
fileprivate let rwlock: UnsafeMutablePointer<SRWLOCK> =
143143
UnsafeMutablePointer.allocate(capacity: 1)
144144
fileprivate var shared: Bool = true
@@ -149,7 +149,9 @@ internal final class ReadWriteLock {
149149

150150
/// Create a new lock.
151151
public init() {
152-
#if os(Windows)
152+
#if canImport(WASILibc)
153+
// WASILibc is single threaded, provides no locks
154+
#elseif os(Windows)
153155
InitializeSRWLock(self.rwlock)
154156
#else
155157
let err = pthread_rwlock_init(self.rwlock, nil)
@@ -158,7 +160,9 @@ internal final class ReadWriteLock {
158160
}
159161

160162
deinit {
161-
#if os(Windows)
163+
#if canImport(WASILibc)
164+
// WASILibc is single threaded, provides no locks
165+
#elseif os(Windows)
162166
// SRWLOCK does not need to be free'd
163167
#else
164168
let err = pthread_rwlock_destroy(self.rwlock)
@@ -172,7 +176,9 @@ internal final class ReadWriteLock {
172176
/// Whenever possible, consider using `withReaderLock` instead of this
173177
/// method and `unlock`, to simplify lock handling.
174178
public func lockRead() {
175-
#if os(Windows)
179+
#if canImport(WASILibc)
180+
// WASILibc is single threaded, provides no locks
181+
#elseif os(Windows)
176182
AcquireSRWLockShared(self.rwlock)
177183
self.shared = true
178184
#else
@@ -186,7 +192,9 @@ internal final class ReadWriteLock {
186192
/// Whenever possible, consider using `withWriterLock` instead of this
187193
/// method and `unlock`, to simplify lock handling.
188194
public func lockWrite() {
189-
#if os(Windows)
195+
#if canImport(WASILibc)
196+
// WASILibc is single threaded, provides no locks
197+
#elseif os(Windows)
190198
AcquireSRWLockExclusive(self.rwlock)
191199
self.shared = false
192200
#else
@@ -201,7 +209,9 @@ internal final class ReadWriteLock {
201209
/// instead of this method and `lockRead` and `lockWrite`, to simplify lock
202210
/// handling.
203211
public func unlock() {
204-
#if os(Windows)
212+
#if canImport(WASILibc)
213+
// WASILibc is single threaded, provides no locks
214+
#elseif os(Windows)
205215
if self.shared {
206216
ReleaseSRWLockShared(self.rwlock)
207217
} else {
@@ -261,4 +271,3 @@ extension ReadWriteLock {
261271
try self.withWriterLock(body)
262272
}
263273
}
264-
#endif

Sources/Logging/LogHandler.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@
113113
/// Please note that the above `LogHandler` will still pass the 'log level is a value' test above it iff the global log
114114
/// level has not been overridden. And most importantly it passes the requirement listed above: A change to the log
115115
/// level on one `Logger` should not affect the log level of another `Logger` variable.
116-
public protocol LogHandler {
116+
public protocol LogHandler: _SwiftLogSendableLogHandler {
117117
/// This method is called when a `LogHandler` must emit a log message. There is no need for the `LogHandler` to
118118
/// check if the `level` is above or below the configured `logLevel` as `Logger` already performed this check and
119119
/// determined that a message should be logged.
@@ -186,3 +186,11 @@ extension LogHandler {
186186
line: line)
187187
}
188188
}
189+
190+
// MARK: - Sendable support helpers
191+
192+
#if compiler(>=5.6)
193+
@preconcurrency public protocol _SwiftLogSendableLogHandler: Sendable {}
194+
#else
195+
public protocol _SwiftLogSendableLogHandler {}
196+
#endif

0 commit comments

Comments
 (0)