-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Spawn a !Send future onto any thread #2545
Comments
Your snippet has the future implementing The reason we don't support this right now is any arbitrary thread can become blocked indefinitely (because of |
It doesn't :) The fn spawn_pinned<Fut: Future + Send + 'static>(f: impl FnOnce() -> Fut + Send + 'static); |
As far as I understand, this feature can be very useful for e.g. |
actix uses |
If you use LocalSet in some async future, this futures becomes !Send, so it cannot be spawned onto Tokio. |
LocalSet is not meant to be used inside a future, instead it should replace your |
I've also wanted this from time to time. It's possible in pub fn spawn_pinned<F, Fut, T>(task: F) -> impl Future<Output = Result<T, JoinError>> + Send
where
F: FnOnce() -> Fut + Send + 'static,
Fut: Future<Output = T> + 'static,
T: Send + 'static,
{
spawn(future::lazy(|_| spawn_local(task())).flatten()).map(Result::unwrap)
} https://play.rust-lang.org/?edition=2018&gist=32cdeabfec85ab510020e0efa9f69e95 |
Once you use |
Currently there doesn't seem to be a good way to spawn This approach is different from spawning a new thread with a single-threaded executor (e.g. actix-web) because the worker can still execute normal |
Well, there is no good way to spawn If you give more details on your database connection, there is likely another way around it. If you ask on our Discord or open a discussion about the specific problem, I'll be happy to help out. |
I am closing this because the feature is incompatible with the existence of Please open a discussion if you need help getting around issues related to this. |
@Darksonn IMO, this is a more important feature than That said, I don't believe |
What happens if you call block_in_place on a thread where !Send futures are executed? |
If you want to run futures on a separate thread from the ordinary worker threads, you can do that with |
@Darksonn with |
@sfackler You need to make sure that you only spawn TBH, edit: Instead, there should be a separate thread-pool for "high latency" tasks where blocking work can be done, and |
I don't think Here's a playground link that demonstrates the issue with a fake database connection ( fn spawn_pinned_alt<Fut: Future>(_f: Fut) -> task::JoinHandle<Fut::Output>; Also (as mentioned above) there's some more context on my particular requirements in graphql-rust/juniper#840. |
I don't agree that The docs for
I have found niche use for
If tasks are high-latency then why not just use I suggest the most straightforward implementation would be to introduce a local task queue on worker threads, which would enable |
It's a bit of an edge case, but you might have a task which is a mixture of async and blocking code, where the blocking part is
This would solve a different problem from the one described in this issue. The idea is that you don't care which thread it runs on, as long as it sticks to that thread. Your suggestion would unnecessarily prohibit spawning such tasks from non-worker threads, and would also prevent tokio from doing any kind of "load balancing" to prevent a single thread from becoming the bottleneck. |
I (perhaps naively) think that having a local task queue in the workers would still allow load balancing since the spawn_pinned API has a |
The |
@alecmocatta you're right, I missed that you were suggesting |
Regarding As for a |
Is this worth adding to tokio-util? |
I just opened a PR to add |
I often want to create a task which will be pinned to a thread. However, when I'm creating the task, I don't care which thread it ends up pinned on.
Essentially I would like a spawn function that looks something like this:
(ie. the
Fut
does not implementSend
)The reason for this is that the future has some internal
!Sync
state that it will access across a yield point.The text was updated successfully, but these errors were encountered: