diff --git a/.github/workflows/swift-package.yml b/.github/workflows/swift-package.yml
index da685a2..265a7dc 100644
--- a/.github/workflows/swift-package.yml
+++ b/.github/workflows/swift-package.yml
@@ -4,8 +4,7 @@ on: [push]
jobs:
build:
-
- runs-on: macos-13
+ runs-on: macos-latest
steps:
- uses: actions/checkout@v2
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/AsyncReactor.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/AsyncReactor.xcscheme
new file mode 100644
index 0000000..c5e1627
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/AsyncReactor.xcscheme
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Reactor.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Reactor.xcscheme
new file mode 100644
index 0000000..04313aa
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/Reactor.xcscheme
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Package.swift b/Package.swift
index 07c446d..015dc91 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,5 +1,4 @@
-// swift-tools-version: 5.7
-// The swift-tools-version declares the minimum version of Swift required to build this package.
+// swift-tools-version: 6.2
import PackageDescription
@@ -12,7 +11,6 @@ let package = Package(
.macOS(.v12)
],
products: [
- // Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "AsyncReactor",
targets: ["AsyncReactor"]
@@ -22,13 +20,8 @@ let package = Package(
targets: ["Reactor"]
)
],
- dependencies: [
- // Dependencies declare other packages that this package depends on.
- // .package(url: /* package url */, from: "1.0.0"),
- ],
+ dependencies: [],
targets: [
- // Targets are the basic building blocks of a package. A target can define a module or a test suite.
- // Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "ReactorBase",
dependencies: []
diff --git a/Package@swift-5.swift b/Package@swift-5.swift
new file mode 100644
index 0000000..32d64c2
--- /dev/null
+++ b/Package@swift-5.swift
@@ -0,0 +1,43 @@
+// swift-tools-version: 5.9
+
+import PackageDescription
+
+let package = Package(
+ name: "AsyncReactor",
+ platforms: [
+ .iOS(.v15),
+ .tvOS(.v15),
+ .watchOS(.v8),
+ .macOS(.v12)
+ ],
+ products: [
+ .library(
+ name: "AsyncReactor",
+ targets: ["AsyncReactor"]
+ ),
+ .library(
+ name: "Reactor",
+ targets: ["Reactor"]
+ )
+ ],
+ dependencies: [],
+ targets: [
+ .target(
+ name: "ReactorBase",
+ dependencies: []
+ ),
+ .target(
+ name: "Reactor",
+ dependencies: ["ReactorBase"]
+ ),
+ .target(
+ name: "AsyncReactor",
+ dependencies: ["ReactorBase"]
+ ),
+ .testTarget(
+ name: "AsyncReactorTests",
+ dependencies: ["AsyncReactor"],
+ path: "Tests"
+ ),
+ ]
+)
diff --git a/Sources/ReactorBase/ReactorBase.swift b/Sources/ReactorBase/ReactorBase.swift
index 48f38f7..34d6dcd 100644
--- a/Sources/ReactorBase/ReactorBase.swift
+++ b/Sources/ReactorBase/ReactorBase.swift
@@ -53,33 +53,40 @@ extension ReactorBase {
// MARK: - Cancellation Support
-public struct CancelId: Hashable {
- let id: AnyHashable
+public struct CancelId: Hashable, Sendable {
+ let id: UUID
let mode: Mode
- public init(id: AnyHashable, mode: Mode) {
+ public init(id: UUID, mode: Mode) {
self.id = id
self.mode = mode
}
- public struct Mode: OptionSet, Hashable {
+ public struct Mode: OptionSet, Hashable, Sendable {
public let rawValue: Int
public init(rawValue: Int) {
self.rawValue = rawValue
}
- public static let lifecycle = Mode(rawValue: 1 << 0)
- public static let inFlight = Mode(rawValue: 1 << 1)
+ public static var lifecycle: Mode {
+ Mode(rawValue: 1 << 0)
+ }
+
+ public static var inFlight: Mode {
+ Mode(rawValue: 1 << 1)
+ }
}
}
-struct TasksHolder {
- @MainActor
- static var tasks = [TaskKey: Task]()
+@MainActor
+class TasksHolder {
+ var tasks = [TaskKey: Task]()
+
+ static var shared: TasksHolder = TasksHolder()
}
-struct TaskKey: Hashable {
+struct TaskKey: Hashable, Sendable {
let reactorId: ObjectIdentifier
let id: CancelId
@@ -95,19 +102,19 @@ extension ReactorBase {
let key = TaskKey(reactor: self, id: id)
if id.mode.contains(.inFlight) {
- TasksHolder.tasks[key]?.cancel()
+ TasksHolder.shared.tasks[key]?.cancel()
}
let task = Task {
await self.action(action)
}
- TasksHolder.tasks[key] = task
+ TasksHolder.shared.tasks[key] = task
await task.value
if !task.isCancelled {
- TasksHolder.tasks.removeValue(forKey: key)
+ TasksHolder.shared.tasks.removeValue(forKey: key)
}
}
@@ -115,26 +122,26 @@ extension ReactorBase {
Task { await self.action(action, id: id) }
}
- public func lifecycleTask(_ action: @escaping @Sendable () async -> Void) {
+ public func lifecycleTask(_ action: @escaping @Sendable () async -> ()) {
Task { @MainActor in
let key = TaskKey(reactor: self, id: .init(id: UUID(), mode: .lifecycle))
let task = Task.detached {
await action()
- await MainActor.run { _ = TasksHolder.tasks.removeValue(forKey: key) }
+ await MainActor.run { _ = TasksHolder.shared.tasks.removeValue(forKey: key) }
}
- TasksHolder.tasks[key] = task
+ TasksHolder.shared.tasks[key] = task
}
}
public func cancelLifecycleTasks() {
Task { @MainActor in
- let keys = TasksHolder.tasks.keys.filter { $0.id.mode.contains(.lifecycle) && $0.reactorId == ObjectIdentifier(self) }
+ let keys = TasksHolder.shared.tasks.keys.filter { $0.id.mode.contains(.lifecycle) && $0.reactorId == ObjectIdentifier(self) }
for key in keys {
- TasksHolder.tasks[key]?.cancel()
- TasksHolder.tasks.removeValue(forKey: key)
+ TasksHolder.shared.tasks[key]?.cancel()
+ TasksHolder.shared.tasks.removeValue(forKey: key)
}
}
}