From 5bf0f2dbad1fc67583d012cee9910f65b901d724 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Thu, 5 Feb 2026 09:54:09 +1100 Subject: [PATCH 1/2] MRP: formatting --- Sources/MRP/Model/Participant.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/MRP/Model/Participant.swift b/Sources/MRP/Model/Participant.swift index 80bc443..46eb6a2 100644 --- a/Sources/MRP/Model/Participant.swift +++ b/Sources/MRP/Model/Participant.swift @@ -1073,7 +1073,8 @@ private final class _AttributeValue: Sendable, Hashable, Equatab attributeType: attributeType, attributeSubtype: attributeSubtype, attributeValue: unwrappedValue, - smFlags: participant._getSmFlags(for: attributeType).union(isReplacingSubtype ? .isReplacingSubtype : []), + smFlags: participant._getSmFlags(for: attributeType) + .union(isReplacingSubtype ? .isReplacingSubtype : []), applicant: applicant, registrar: registrar ) From f32f4e2b4b1332b5e71f2af0c310c12973c45493 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Thu, 5 Feb 2026 09:54:13 +1100 Subject: [PATCH 2/2] MRP: enqueue application join and leave indications in order --- Package.swift | 5 +++-- Sources/MRP/Model/Participant.swift | 12 ++++-------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Package.swift b/Package.swift index 64e137c..a943174 100644 --- a/Package.swift +++ b/Package.swift @@ -18,7 +18,7 @@ var PlatformLinkerSettings: [LinkerSetting] = [] PlatformPackageDependencies = [ .package( url: "https://github.com/PADL/IORingSwift", - from: "0.1.2" + from: "0.9.9" ), .package( url: "https://github.com/PADL/NetLinkSwift", @@ -112,6 +112,7 @@ let CommonPackageDependencies: [Package.Dependency] = [ .package(url: "https://github.com/swhitty/FlyingFoxMacros", from: "0.2.0"), .package(url: "https://github.com/Flight-School/AnyCodable", from: "0.6.7"), .package(url: "https://github.com/apple/swift-binary-parsing", from: "0.0.1"), + .package(url: "https://github.com/dfed/swift-async-queue", from: "1.0.0"), ] let CommonProducts: [Product] = [ @@ -157,7 +158,7 @@ let CommonTargets: [Target] = [ .product(name: "SystemPackage", package: "swift-system"), .product(name: "FlyingFox", package: "FlyingFox"), .product(name: "FlyingFoxMacros", package: "FlyingFoxMacros"), - + .product(name: "AsyncQueue", package: "swift-async-queue"), ] + PlatformTargetDependencies, cSettings: PlatformCSettings, swiftSettings: PlatformSwiftSettings, diff --git a/Sources/MRP/Model/Participant.swift b/Sources/MRP/Model/Participant.swift index 46eb6a2..f89c346 100644 --- a/Sources/MRP/Model/Participant.swift +++ b/Sources/MRP/Model/Participant.swift @@ -35,6 +35,7 @@ // identifies the set of Bridge Ports that form the applicable active topology // (8.4). +import AsyncQueue import IEEE802 import Logging import Synchronization @@ -128,6 +129,7 @@ public final class Participant: Equatable, Hashable, CustomStrin fileprivate let _logger: Logger fileprivate let _type: ParticipantType + fileprivate let _queue = ActorQueue() fileprivate nonisolated var controller: MRPController? { _controller.object } nonisolated var application: A? { _application.object } @@ -143,6 +145,7 @@ public final class Participant: Equatable, Hashable, CustomStrin ) { _controller = Weak(controller) _application = Weak(application) + _queue.adoptExecutionContext(of: application) self.contextIdentifier = contextIdentifier self.port = port @@ -1197,14 +1200,7 @@ private final class _AttributeValue: Sendable, Hashable, Equatab // the subsequent join guard !context.smFlags.contains(.isReplacingSubtype) else { return } - // running application indications in unstructured tasks is a trade-off; it - // allows us to make the participant API as consumed by the application - // synchronous, thereby avoiding reentrancy issues; but it does not - // completely eliminate the possibility of race conditions as different - // values of the same attribute, or related attributes, are processed (as - // Tasks are not necessarily scheduled in order). If this proves to be - // problematic, we should look at using a queue of tasks instead. - Task { @Sendable in + Task(on: context.participant._queue) { @Sendable _ in switch registrarAction { case .New: fallthrough