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

block_on from local runtime, like tokio #116

Closed
zzau13 opened this issue Oct 18, 2022 · 6 comments
Closed

block_on from local runtime, like tokio #116

zzau13 opened this issue Oct 18, 2022 · 6 comments
Assignees
Labels
F-feature-request feature request

Comments

@zzau13
Copy link
Contributor

zzau13 commented Oct 18, 2022

I need to be able to fetch the current runtime of each thread and call blocking methods.
How does tokio with the functions

I think I could implement it.

Edit:

I see that it is quite difficult to get a local Executor because it depends on the Driver trait. I'm doing tests removing everything that is not ui-ring. It may fork you. With this I come to say that there is no rush with the issue and thank you for your work. I have already seen that you have it reflected in #8

@zzau13 zzau13 added the F-feature-request feature request label Oct 18, 2022
@zzau13 zzau13 changed the title [feature] block_on from local runtime, like tokio block_on from local runtime, like tokio Oct 18, 2022
@zzau13 zzau13 closed this as completed Oct 18, 2022
@ihciah
Copy link
Member

ihciah commented Oct 18, 2022

Thanks! I don't know if it is proper for a thread-per-core runtime to have a built in thread pool. If we meant for let user sense every thread and every detail, maybe users can do it by their own? For example they may start a thread pool and do communication by their own? I haven't figured out what it should be, or if users can do this job purely by their own, or how to implement it yet. If you have any thought, please comment! :)

@ihciah
Copy link
Member

ihciah commented Oct 18, 2022

I thought about it and I think maybe we have to implement it because users cannot touch the runtime internal components.
The main problem is how to wait task executed, and we can impl it as do wake in another thread. Since tasks only run on the thread that it belongs to, we may send the waker to the owner thread like what we have done for awaiting between different threads.
And the wakers sender of every runtime thread are not exposed to users, also the task related structs are not either. So users cannot implement it.
I will follow this feature recently, and will update the details here. If you are willing for doing something, please feel free to comment and I will appreciate it.

@ihciah ihciah reopened this Oct 18, 2022
@ihciah
Copy link
Member

ihciah commented Oct 18, 2022

Mistake correction:
Implement spawn_blocking by users is possible, but may waste a thread, complicated and hard.

Since we have to recv the thread pool result, and we may wait for it with a sync channel, so in this thread we cannot spawn any other task or it will be blocked.

If we start a single thread with monoio runtime and let it do this single one thing:

  1. result = channel.recv() // may block the thread but it's ok
  2. waker.wake() // will infact send the waker to its owner and wake there, requires sync feature
    It will work.

So if let users impl it, he/she has to:

  1. impl a thread pool
  2. spawn a thread and start monoio runtime on it
  3. in the runtime, do recv from thread pool and wake related waker

If we impl it inside the runtime, we can save a seprated thread, and users don't have to do these complicated things including impl a thread pool.

Something to think about: use a global thread pool or one thread pool for each runtime? Since creating threads are expensive, maybe we should share one thread pool between runtime threads. But it will be better if we can let user decide it.

And it will cause api changing. An initial idea:

  • Solution 1:
    Let user create shared ThreadPool(something like Arc<ThreadPoolInner> and cloneable) by their own, and pass it to RuntimeBuilder.
    Expose api like monoio::spawn_blocking.
    Distinguish whether a thread pool is attached may cause its hard to use, so we can hide the problem by just execute the blocking task directly on current thread if no thread pool attached. Or we can return error out(like Error::NoThreadPoolAttached).

  • Solution 2:
    User create ThreadPool by their own, and he/she need to use pool.spawn_blocking(). The disadvantage of this solution is that user must hold the thread pool by their own and pass it for every spawn_blocking.
    Usually, every CPU-intensive task should be spawn_blocking instantly. It cannot be mixed with async code, once mixed it cannot be splitted out and may block the runtime thread. So for a library, it has to call spawn_blocking if it want to do some big calculation. Passing thread pool to every library is an unrealistic task.

Here I think maybe we can take solution 1. If anyone have some different ideas, feel free to comment.

@zzau13
Copy link
Contributor Author

zzau13 commented Oct 18, 2022

I don't need the runtime inside each thread of the threadpool so that executing a function is enough, i.e., spawn_blocking(FnOnce) -> Future. Solution 1 I think could work well. You pass the threadpool to it from outside, if you want, and that's it.

@zzau13
Copy link
Contributor Author

zzau13 commented Oct 27, 2022

Spawn_blocking with non-blocking methods inside it doesn't make sense, since as its name indicates it must block and there are other methods to launch non-blocking methods in other threads. I think the best option is to separate this method from the Runtime and support it with another crate. I close this issue.

@zzau13 zzau13 closed this as completed Oct 27, 2022
@ihciah
Copy link
Member

ihciah commented Oct 28, 2022

I didn't get what you mean...
Here I implement a draft #124 . It provides a similar function spawn_blocking like tokio. With this function it can execute the lambda in another thread(users may implement a thread pool by their own or use DefaultThreadPool we provided). And in original worker thread, you get a JoinHandle, no matter you wait for it or not, the lambda will be executed, and this does not affect other tasks on current worker thread.

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

No branches or pull requests

2 participants