diff --git a/Sources/NIO/ByteBuffer-core.swift b/Sources/NIO/ByteBuffer-core.swift index 23d96fd8b9..730d086b1c 100644 --- a/Sources/NIO/ByteBuffer-core.swift +++ b/Sources/NIO/ByteBuffer-core.swift @@ -86,8 +86,10 @@ public struct ByteBufferAllocator { hookedRealloc: @escaping @convention(c) (UnsafeMutableRawPointer?, Int) -> UnsafeMutableRawPointer?, hookedFree: @escaping @convention(c) (UnsafeMutableRawPointer?) -> Void, hookedMemcpy: @escaping @convention(c) (UnsafeMutableRawPointer, UnsafeRawPointer, Int) -> Void) { - assert(MemoryLayout.size <= 3 * MemoryLayout.size, - "ByteBuffer has size \(MemoryLayout.size) which is larger than the built-in storage of the existential containers.") + #if !arch(arm) // only complain on 64-bit, this is unfortunate reality on 32-bit + assert(MemoryLayout.size <= 3 * MemoryLayout.size, + "ByteBuffer has size \(MemoryLayout.size) which is larger than the built-in storage of the existential containers.") + #endif self.malloc = hookedMalloc self.realloc = hookedRealloc self.free = hookedFree diff --git a/Sources/NIO/ChannelHandlers.swift b/Sources/NIO/ChannelHandlers.swift index 4338eb2ab3..0701482815 100644 --- a/Sources/NIO/ChannelHandlers.swift +++ b/Sources/NIO/ChannelHandlers.swift @@ -24,7 +24,7 @@ public final class AcceptBackoffHandler: ChannelDuplexHandler { public typealias InboundIn = Channel public typealias OutboundIn = Channel - private var nextReadDeadlineNS: Int? + private var nextReadDeadlineNS: TimeAmount.Value? private let backoffProvider: (IOError) -> TimeAmount? private var scheduledRead: Scheduled? @@ -46,7 +46,7 @@ public final class AcceptBackoffHandler: ChannelDuplexHandler { guard scheduledRead == nil else { return } if let deadline = self.nextReadDeadlineNS { - let now = Int(DispatchTime.now().uptimeNanoseconds) + let now = TimeAmount.Value(DispatchTime.now().uptimeNanoseconds) if now >= deadline { // The backoff already expired, just do a read. doRead(ctx) @@ -62,7 +62,7 @@ public final class AcceptBackoffHandler: ChannelDuplexHandler { public func errorCaught(ctx: ChannelHandlerContext, error: Error) { if let ioError = error as? IOError { if let amount = backoffProvider(ioError) { - self.nextReadDeadlineNS = Int(DispatchTime.now().uptimeNanoseconds) + amount.nanoseconds + self.nextReadDeadlineNS = TimeAmount.Value(DispatchTime.now().uptimeNanoseconds) + amount.nanoseconds if let scheduled = self.scheduledRead { scheduled.cancel() scheduleRead(in: amount, ctx: ctx) @@ -246,7 +246,7 @@ public class IdleStateHandler: ChannelDuplexHandler { return } - let diff = Int(DispatchTime.now().uptimeNanoseconds) - Int(self.lastReadTime.uptimeNanoseconds) + let diff = TimeAmount.Value(DispatchTime.now().uptimeNanoseconds) - TimeAmount.Value(self.lastReadTime.uptimeNanoseconds) if diff >= timeout.nanoseconds { // Reader is idle - set a new timeout and trigger an event through the pipeline self.scheduledReaderTask = ctx.eventLoop.scheduleTask(in: timeout, self.newReadTimeoutTask(ctx, timeout)) @@ -275,7 +275,7 @@ public class IdleStateHandler: ChannelDuplexHandler { ctx.fireUserInboundEventTriggered(IdleStateEvent.write) } else { // Write occurred before the timeout - set a new timeout with shorter delay. - self.scheduledWriterTask = ctx.eventLoop.scheduleTask(in: .nanoseconds(Int(timeout.nanoseconds) - Int(diff)), self.newWriteTimeoutTask(ctx, timeout)) + self.scheduledWriterTask = ctx.eventLoop.scheduleTask(in: .nanoseconds(TimeAmount.Value(timeout.nanoseconds) - TimeAmount.Value(diff)), self.newWriteTimeoutTask(ctx, timeout)) } } } @@ -293,7 +293,7 @@ public class IdleStateHandler: ChannelDuplexHandler { let lastRead = self.lastReadTime let lastWrite = self.lastWriteCompleteTime - let diff = Int(DispatchTime.now().uptimeNanoseconds) - Int((lastRead > lastWrite ? lastRead : lastWrite).uptimeNanoseconds) + let diff = TimeAmount.Value(DispatchTime.now().uptimeNanoseconds) - TimeAmount.Value((lastRead > lastWrite ? lastRead : lastWrite).uptimeNanoseconds) if diff >= timeout.nanoseconds { // Reader is idle - set a new timeout and trigger an event through the pipeline self.scheduledReaderTask = ctx.eventLoop.scheduleTask(in: timeout, self.newAllTimeoutTask(ctx, timeout)) @@ -301,7 +301,7 @@ public class IdleStateHandler: ChannelDuplexHandler { ctx.fireUserInboundEventTriggered(IdleStateEvent.all) } else { // Read occurred before the timeout - set a new timeout with shorter delay. - self.scheduledReaderTask = ctx.eventLoop.scheduleTask(in: .nanoseconds(Int(timeout.nanoseconds) - diff), self.newAllTimeoutTask(ctx, timeout)) + self.scheduledReaderTask = ctx.eventLoop.scheduleTask(in: .nanoseconds(TimeAmount.Value(timeout.nanoseconds) - diff), self.newAllTimeoutTask(ctx, timeout)) } } } diff --git a/Sources/NIO/EventLoop.swift b/Sources/NIO/EventLoop.swift index d841d935bb..c320ee5808 100644 --- a/Sources/NIO/EventLoop.swift +++ b/Sources/NIO/EventLoop.swift @@ -98,10 +98,17 @@ public protocol EventLoop: EventLoopGroup { /// /// - note: `TimeAmount` should not be used to represent a point in time. public struct TimeAmount { + + #if arch(arm) // 32-bit, Raspi/AppleWatch/etc + public typealias Value = Int64 + #else // 64-bit, keeping that at Int for SemVer in the 1.x line. + public typealias Value = Int + #endif + /// The nanoseconds representation of the `TimeAmount`. - public let nanoseconds: Int + public let nanoseconds: Value - private init(_ nanoseconds: Int) { + private init(_ nanoseconds: Value) { self.nanoseconds = nanoseconds } @@ -110,7 +117,7 @@ public struct TimeAmount { /// - parameters: /// - amount: the amount of nanoseconds this `TimeAmount` represents. /// - returns: the `TimeAmount` for the given amount. - public static func nanoseconds(_ amount: Int) -> TimeAmount { + public static func nanoseconds(_ amount: Value) -> TimeAmount { return TimeAmount(amount) } @@ -119,7 +126,7 @@ public struct TimeAmount { /// - parameters: /// - amount: the amount of microseconds this `TimeAmount` represents. /// - returns: the `TimeAmount` for the given amount. - public static func microseconds(_ amount: Int) -> TimeAmount { + public static func microseconds(_ amount: Value) -> TimeAmount { return TimeAmount(amount * 1000) } @@ -128,7 +135,7 @@ public struct TimeAmount { /// - parameters: /// - amount: the amount of milliseconds this `TimeAmount` represents. /// - returns: the `TimeAmount` for the given amount. - public static func milliseconds(_ amount: Int) -> TimeAmount { + public static func milliseconds(_ amount: Value) -> TimeAmount { return TimeAmount(amount * 1000 * 1000) } @@ -137,7 +144,7 @@ public struct TimeAmount { /// - parameters: /// - amount: the amount of seconds this `TimeAmount` represents. /// - returns: the `TimeAmount` for the given amount. - public static func seconds(_ amount: Int) -> TimeAmount { + public static func seconds(_ amount: Value) -> TimeAmount { return TimeAmount(amount * 1000 * 1000 * 1000) } @@ -146,7 +153,7 @@ public struct TimeAmount { /// - parameters: /// - amount: the amount of minutes this `TimeAmount` represents. /// - returns: the `TimeAmount` for the given amount. - public static func minutes(_ amount: Int) -> TimeAmount { + public static func minutes(_ amount: Value) -> TimeAmount { return TimeAmount(amount * 1000 * 1000 * 1000 * 60) } @@ -155,7 +162,7 @@ public struct TimeAmount { /// - parameters: /// - amount: the amount of hours this `TimeAmount` represents. /// - returns: the `TimeAmount` for the given amount. - public static func hours(_ amount: Int) -> TimeAmount { + public static func hours(_ amount: Value) -> TimeAmount { return TimeAmount(amount * 1000 * 1000 * 1000 * 60 * 60) } } @@ -755,19 +762,19 @@ final public class MultiThreadedEventLoopGroup: EventLoopGroup { private final class ScheduledTask { let task: () -> Void private let failFn: (Error) ->() - private let readyTime: Int + private let readyTime: TimeAmount.Value init(_ task: @escaping () -> Void, _ failFn: @escaping (Error) -> Void, _ time: TimeAmount) { self.task = task self.failFn = failFn - self.readyTime = time.nanoseconds + Int(DispatchTime.now().uptimeNanoseconds) + self.readyTime = time.nanoseconds + TimeAmount.Value(DispatchTime.now().uptimeNanoseconds) } func readyIn(_ t: DispatchTime) -> TimeAmount { if readyTime < t.uptimeNanoseconds { return .nanoseconds(0) } - return .nanoseconds(readyTime - Int(t.uptimeNanoseconds)) + return .nanoseconds(readyTime - TimeAmount.Value(t.uptimeNanoseconds)) } func fail(error: Error) { diff --git a/Sources/NIO/Selector.swift b/Sources/NIO/Selector.swift index 26b7434712..391fcc458d 100644 --- a/Sources/NIO/Selector.swift +++ b/Sources/NIO/Selector.swift @@ -22,10 +22,10 @@ private enum SelectorLifecycleState { private extension timespec { init(timeAmount amount: TimeAmount) { - let nsecPerSec: Int = 1_000_000_000 + let nsecPerSec: TimeAmount.Value = 1_000_000_000 let ns = amount.nanoseconds let sec = ns / nsecPerSec - self = timespec(tv_sec: sec, tv_nsec: ns - sec * nsecPerSec) + self = timespec(tv_sec: Int(sec), tv_nsec: Int(ns - sec * nsecPerSec)) } } diff --git a/Sources/NIOConcurrencyHelpers/atomics.swift b/Sources/NIOConcurrencyHelpers/atomics.swift index df2249bdd5..cd0828a422 100644 --- a/Sources/NIOConcurrencyHelpers/atomics.swift +++ b/Sources/NIOConcurrencyHelpers/atomics.swift @@ -474,11 +474,11 @@ extension UInt: AtomicPrimitive { /// /// It behaves very much like `Atomic` but for objects, maintaining the correct retain counts. public class AtomicBox { - private let storage: Atomic + private let storage: Atomic public init(value: T) { let ptr = Unmanaged.passRetained(value) - self.storage = Atomic(value: Int(bitPattern: ptr.toOpaque())) + self.storage = Atomic(value: UInt(bitPattern: ptr.toOpaque())) } deinit { @@ -507,8 +507,8 @@ public class AtomicBox { let expectedPtr = Unmanaged.passUnretained(expected) let desiredPtr = Unmanaged.passUnretained(desired) - if self.storage.compareAndExchange(expected: Int(bitPattern: expectedPtr.toOpaque()), - desired: Int(bitPattern: desiredPtr.toOpaque())) { + if self.storage.compareAndExchange(expected: UInt(bitPattern: expectedPtr.toOpaque()), + desired: UInt(bitPattern: desiredPtr.toOpaque())) { _ = desiredPtr.retain() expectedPtr.release() return true @@ -528,7 +528,7 @@ public class AtomicBox { /// - Returns: The value previously held by this object. public func exchange(with value: T) -> T { let newPtr = Unmanaged.passRetained(value) - let oldPtrBits = self.storage.exchange(with: Int(bitPattern: newPtr.toOpaque())) + let oldPtrBits = self.storage.exchange(with: UInt(bitPattern: newPtr.toOpaque())) let oldPtr = Unmanaged.fromOpaque(UnsafeRawPointer(bitPattern: oldPtrBits)!) return oldPtr.takeRetainedValue() } diff --git a/Sources/NIOHTTP1/HTTPDecoder.swift b/Sources/NIOHTTP1/HTTPDecoder.swift index 5dba802a00..380a3ba9c9 100644 --- a/Sources/NIOHTTP1/HTTPDecoder.swift +++ b/Sources/NIOHTTP1/HTTPDecoder.swift @@ -379,7 +379,7 @@ public class HTTPDecoder: ByteToMessageDecoder, AnyHTTPDecoder { public func decoderRemoved(ctx: ChannelHandlerContext) { // Remove the stored reference to ChannelHandlerContext - parser.data = UnsafeMutableRawPointer(bitPattern: 0x0000deadbeef0000) + parser.data = UnsafeMutableRawPointer(bitPattern: 0xdeadbeef as UInt) // Set the callbacks to nil as we dont need these anymore settings.on_body = nil diff --git a/Sources/NIOHTTP1Server/main.swift b/Sources/NIOHTTP1Server/main.swift index cc5730329b..5eaca8e6d4 100644 --- a/Sources/NIOHTTP1Server/main.swift +++ b/Sources/NIOHTTP1Server/main.swift @@ -249,7 +249,7 @@ private final class HTTPHandler: ChannelInboundHandler { return { ctx, req in self.handleJustWrite(ctx: ctx, request: req, string: "Hello World\r\n", - delay: Int(howLong).map { .milliseconds($0) } ?? .seconds(0)) + delay: TimeAmount.Value(howLong).map { .milliseconds($0) } ?? .seconds(0)) } }