Skip to content

Commit

Permalink
Use package ACL for v2 (grpc#1976)
Browse files Browse the repository at this point in the history
Motivation:

v2 uses '@_spi(Package)' in a number of places. Now that we require a
Swift 6 compiler the 'package' access modifier can be used in its place.

Modifications:

- replace `@_spi(Package)` with `package`
- use `package` access instead of `@testable`
- remove a number of backports required for older compiler versions
  which are no longer necessary

Result:

- Less use of underscored API
  • Loading branch information
glbrntt committed Jul 10, 2024
1 parent 0f9da0c commit 6bcc734
Show file tree
Hide file tree
Showing 49 changed files with 209 additions and 497 deletions.
3 changes: 1 addition & 2 deletions Sources/GRPCCore/Call/Client/CallOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 127,7 @@ extension CallOptions {

@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
extension CallOptions {
@_spi(Package)
public mutating func formUnion(with methodConfig: MethodConfig?) {
package mutating func formUnion(with methodConfig: MethodConfig?) {
guard let methodConfig = methodConfig else { return }

self.timeout.setIfNone(to: methodConfig.timeout)
Expand Down
6 changes: 2 additions & 4 deletions Sources/GRPCCore/Coding/CompressionAlgorithm.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 16,13 @@

/// Message compression algorithms.
public struct CompressionAlgorithm: Hashable, Sendable {
@_spi(Package)
public enum Value: UInt8, Hashable, Sendable, CaseIterable {
package enum Value: UInt8, Hashable, Sendable, CaseIterable {
case none = 0
case deflate
case gzip
}

@_spi(Package)
public let value: Value
package let value: Value

fileprivate init(_ algorithm: Value) {
self.value = algorithm
Expand Down
23 changes: 11 additions & 12 deletions Sources/GRPCCore/Internal/Concurrency Primitives/Lock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -237,49 237,48 @@ extension UnsafeMutablePointer {
}

@usableFromInline
internal typealias LockedValueBox<Value> = _LockedValueBox<Value>

// TODO: Use 'package' ACL when 5.9 is the minimum Swift version.
public struct _LockedValueBox<Value> {
package struct LockedValueBox<Value> {
@usableFromInline
let storage: LockStorage<Value>

@inlinable
public init(_ value: Value) {
package init(_ value: Value) {
self.storage = .create(value: value)
}
@inlinable
public func withLockedValue<T>(_ mutate: (inout Value) throws -> T) rethrows -> T {
package func withLockedValue<T>(_ mutate: (inout Value) throws -> T) rethrows -> T {
return try self.storage.withLockedValue(mutate)
}

/// An unsafe view over the locked value box.
///
/// Prefer ``withLockedValue(_:)`` where possible.
public var unsafe: Unsafe {
@usableFromInline
package var unsafe: Unsafe {
Unsafe(storage: self.storage)
}

public struct Unsafe {
@usableFromInline
package struct Unsafe {
@usableFromInline
let storage: LockStorage<Value>

/// Manually acquire the lock.
@inlinable
public func lock() {
package func lock() {
self.storage.lock()
}

/// Manually release the lock.
@inlinable
public func unlock() {
package func unlock() {
self.storage.unlock()
}

/// Mutate the value, assuming the lock has been acquired manually.
@inlinable
public func withValueAssumingLockIsAcquired<T>(
package func withValueAssumingLockIsAcquired<T>(
_ mutate: (inout Value) throws -> T
) rethrows -> T {
return try self.storage.withUnsafeMutablePointerToHeader { value in
Expand All @@ -289,4 288,4 @@ public struct _LockedValueBox<Value> {
}
}

extension _LockedValueBox: Sendable where Value: Sendable {}
extension LockedValueBox: Sendable where Value: Sendable {}
12 changes: 5 additions & 7 deletions Sources/GRPCCore/Internal/MethodConfigs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 14,6 @@
* limitations under the License.
*/

// TODO: when swift(>=5.9), use 'package' access level

/// A collection of ``MethodConfig``s, mapped to specific methods or services.
///
/// When creating a new instance, no overrides and no default will be set for using when getting
Expand All @@ -25,13 23,13 @@
///
/// Use the subscript to get and set configurations for specific methods.
@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
public struct _MethodConfigs: Sendable, Hashable {
package struct MethodConfigs: Sendable, Hashable {
private var elements: [MethodConfig.Name: MethodConfig]

/// Create a new ``_MethodConfigs``.
///
/// - Parameter serviceConfig: The configuration to read ``MethodConfig`` from.
public init(serviceConfig: ServiceConfig = ServiceConfig()) {
package init(serviceConfig: ServiceConfig = ServiceConfig()) {
self.elements = [:]

for configuration in serviceConfig.methodConfig {
Expand All @@ -52,7 50,7 @@ public struct _MethodConfigs: Sendable, Hashable {
///
/// - Parameters:
/// - descriptor: The ``MethodDescriptor`` for which to get or set a ``MethodConfig``.
public subscript(_ descriptor: MethodDescriptor) -> MethodConfig? {
package subscript(_ descriptor: MethodDescriptor) -> MethodConfig? {
get {
var name = MethodConfig.Name(service: descriptor.service, method: descriptor.method)

Expand Down Expand Up @@ -81,7 79,7 @@ public struct _MethodConfigs: Sendable, Hashable {
/// Set a default configuration for all methods that have no overrides.
///
/// - Parameter configuration: The default configuration.
public mutating func setDefaultConfiguration(_ configuration: MethodConfig?) {
package mutating func setDefaultConfiguration(_ configuration: MethodConfig?) {
let name = MethodConfig.Name(service: "", method: "")
self.elements[name] = configuration
}
Expand All @@ -95,7 93,7 @@ public struct _MethodConfigs: Sendable, Hashable {
/// - Parameters:
/// - configuration: The default configuration for the service.
/// - service: The name of the service for which this override applies.
public mutating func setDefaultConfiguration(
package mutating func setDefaultConfiguration(
_ configuration: MethodConfig?,
forService service: String
) {
Expand Down
29 changes: 0 additions & 29 deletions Sources/GRPCCore/Internal/Task SleepBackport.swift

This file was deleted.

32 changes: 0 additions & 32 deletions Sources/GRPCCore/Streaming/Internal/AsyncStream MakeStream.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -18,9 18,8 @@ import NIOCore
import NIOHTTP2

/// An event which happens on a client's HTTP/2 connection.
@_spi(Package)
public enum ClientConnectionEvent: Sendable {
public enum CloseReason: Sendable {
package enum ClientConnectionEvent: Sendable {
package enum CloseReason: Sendable {
/// The server sent a GOAWAY frame to the client.
case goAway(HTTP2ErrorCode, String)
/// The keep alive timer fired and subsequently timed out.
Expand Down Expand Up @@ -49,14 48,14 @@ public enum ClientConnectionEvent: Sendable {
/// 3. Forwarding lifecycle events to the next handler.
///
/// Some of the behaviours are described in [gRFC A8](https://github.com/grpc/proposal/blob/master/A8-client-side-keepalive.md).
final class ClientConnectionHandler: ChannelInboundHandler, ChannelOutboundHandler {
typealias InboundIn = HTTP2Frame
typealias InboundOut = ClientConnectionEvent
package final class ClientConnectionHandler: ChannelInboundHandler, ChannelOutboundHandler {
package typealias InboundIn = HTTP2Frame
package typealias InboundOut = ClientConnectionEvent

typealias OutboundIn = Never
typealias OutboundOut = HTTP2Frame
package typealias OutboundIn = Never
package typealias OutboundOut = HTTP2Frame

enum OutboundEvent: Hashable, Sendable {
package enum OutboundEvent: Hashable, Sendable {
/// Close the connection gracefully
case closeGracefully
}
Expand Down Expand Up @@ -103,7 102,7 @@ final class ClientConnectionHandler: ChannelInboundHandler, ChannelOutboundHandl
/// is received.
/// - keepaliveWithoutCalls: Whether the client sends keep-alive pings when there are no calls
/// in progress.
init(
package init(
eventLoop: any EventLoop,
maxIdleTime: TimeAmount?,
keepaliveTime: TimeAmount?,
Expand All @@ -121,16 120,16 @@ final class ClientConnectionHandler: ChannelInboundHandler, ChannelOutboundHandl
self.inReadLoop = false
}

func handlerAdded(context: ChannelHandlerContext) {
package func handlerAdded(context: ChannelHandlerContext) {
assert(context.eventLoop === self.eventLoop)
self.context = context
}

func handlerRemoved(context: ChannelHandlerContext) {
package func handlerRemoved(context: ChannelHandlerContext) {
self.context = nil
}

func channelInactive(context: ChannelHandlerContext) {
package func channelInactive(context: ChannelHandlerContext) {
switch self.state.closed() {
case .none:
()
Expand All @@ -147,7 146,7 @@ final class ClientConnectionHandler: ChannelInboundHandler, ChannelOutboundHandl
self.keepaliveTimeoutTimer.cancel()
}

func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {
package func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {
switch event {
case let event as NIOHTTP2StreamCreatedEvent:
self._streamCreated(event.streamID, channel: context.channel)
Expand All @@ -162,15 161,15 @@ final class ClientConnectionHandler: ChannelInboundHandler, ChannelOutboundHandl
context.fireUserInboundEventTriggered(event)
}

func errorCaught(context: ChannelHandlerContext, error: any Error) {
package func errorCaught(context: ChannelHandlerContext, error: any Error) {
// Store the error and close, this will result in the final close event being fired down
// the pipeline with an appropriate close reason and appropriate error. (This avoids
// the async channel just throwing the error.)
self.state.receivedError(error)
context.close(mode: .all, promise: nil)
}

func channelRead(context: ChannelHandlerContext, data: NIOAny) {
package func channelRead(context: ChannelHandlerContext, data: NIOAny) {
let frame = self.unwrapInboundIn(data)
self.inReadLoop = true

Expand Down Expand Up @@ -229,7 228,7 @@ final class ClientConnectionHandler: ChannelInboundHandler, ChannelOutboundHandl
}
}

func channelReadComplete(context: ChannelHandlerContext) {
package func channelReadComplete(context: ChannelHandlerContext) {
while self.flushPending {
self.flushPending = false
context.flush()
Expand All @@ -239,7 238,7 @@ final class ClientConnectionHandler: ChannelInboundHandler, ChannelOutboundHandl
context.fireChannelReadComplete()
}

func triggerUserOutboundEvent(
package func triggerUserOutboundEvent(
context: ChannelHandlerContext,
event: Any,
promise: EventLoopPromise<Void>?
Expand Down Expand Up @@ -294,7 293,7 @@ extension ClientConnectionHandler {
}

extension ClientConnectionHandler {
struct HTTP2StreamDelegate: @unchecked Sendable, NIOHTTP2StreamDelegate {
package struct HTTP2StreamDelegate: @unchecked Sendable, NIOHTTP2StreamDelegate {
// @unchecked is okay: the only methods do the appropriate event-loop dance.

private let handler: ClientConnectionHandler
Expand All @@ -303,7 302,7 @@ extension ClientConnectionHandler {
self.handler = handler
}

func streamCreated(_ id: HTTP2StreamID, channel: any Channel) {
package func streamCreated(_ id: HTTP2StreamID, channel: any Channel) {
if self.handler.eventLoop.inEventLoop {
self.handler._streamCreated(id, channel: channel)
} else {
Expand All @@ -313,7 312,7 @@ extension ClientConnectionHandler {
}
}

func streamClosed(_ id: HTTP2StreamID, channel: any Channel) {
package func streamClosed(_ id: HTTP2StreamID, channel: any Channel) {
if self.handler.eventLoop.inEventLoop {
self.handler._streamClosed(id, channel: channel)
} else {
Expand All @@ -324,7 323,7 @@ extension ClientConnectionHandler {
}
}

var http2StreamDelegate: HTTP2StreamDelegate {
package var http2StreamDelegate: HTTP2StreamDelegate {
return HTTP2StreamDelegate(self)
}

Expand Down
Loading

0 comments on commit 6bcc734

Please sign in to comment.