Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async Init Support for Actors? #211

Closed
joeljfischer opened this issue Jun 24, 2024 · 3 comments
Closed

Async Init Support for Actors? #211

joeljfischer opened this issue Jun 24, 2024 · 3 comments

Comments

@joeljfischer
Copy link

I'm not sure how possible this would be, but it would vastly simplify some code that I'm moving into Actors for Swift 6 to allow it to use init() async and set up things like a for await loop directly within the initializer and eliminate possible data races by using Task in the initializer.

If it's not possible, then that's understandable, but it would be a great boon to using actor with Factory in certain use cases where things have to be set-up at initialization time.

@hmlongco
Copy link
Owner

hmlongco commented Jun 25, 2024

Will peek, but doubt this will occur as I suspect it would require every step in the resolution chain (registration, caching, etc.) to also support async instances which would then mess with synchronous resolutions.

Might want to consider one of the two following approaches:

// something with an asynchronous initializer
struct AsyncInit {
    let a: Int
    init() async {
        a = 1
    }
}

// generic wrapper for any asynchronous initializer
struct AsyncInitWrapper<T> {
    let wrapped: () async -> T
}

extension Container {
    // Factory using initialization wrapper
    var someAsyncObject: Factory<AsyncInitWrapper<AsyncInit>> {
        self {
            AsyncInitWrapper { await AsyncInit() }
        }
    }
    // Factory using Task isolated context
    var taskAsyncObject: Factory<Task<AsyncInit, Never>> {
        self {
            Task { await AsyncInit() }
        }
    }
}

func testAsyncInit() {
    Task {
        let a1 = await Container.shared.someAsyncObject().wrapped()
        let a2 = await Container.shared.taskAsyncObject().value
    }
}

@hmlongco
Copy link
Owner

Yeah, not going to work. Better to use one of the options shown earlier.

@hmlongco hmlongco pinned this issue Jun 26, 2024
@hmlongco
Copy link
Owner

As mentioned, it would require every step in the resolution chain (registration, caching, etc.) to also support async instances which would then mess with synchronous resolutions. Or half the supporting infrastructure would have to be cloned to support async factories.

Too many easy options available for the rare case in which you're want to do it, as shown earlier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants