-
Notifications
You must be signed in to change notification settings - Fork 3
Conversation
I've made several updates to the RFC based on the feedback here, but due to a Github glitch, I need to put this in a new PR. In any case, here are the key changes:
|
Thanks for the update. Re: The documentation states:
Given that In general, the expected usage patterns of Re: I think the What the RFC refers to as Re: I think the API described would technically work to allow hooking in a current thread executor, but it would require an additional layer of indirection (similar to how I think the best option here is just going to be for This should avoid that extra layer of indirection. |
tokio-reform.md
Outdated
// with Tokio, read and write components are distinct: | ||
let (reader, writer) = conn.split(); | ||
|
||
CurrentThread.spawn(async { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this is still using the older CurrentThread
.
#![feature(conservative_impl_trait)] | ||
|
||
extern crate futures; | ||
extern crate tokio_core; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For clarity, I think all examples based on tokio
and not tokio-core
should use extern crate tokio
and use tokio::xyz
below.
As I mentioned before, error type should be
Because future is not meant to return an error, it must handle error itself and return success. |
While it'd be neat to use |
tokio-reform.md
Outdated
|
||
```rust | ||
impl Timeout { | ||
fn new(dur: Duration) -> Result<Timeout> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we defer the error here into the Future
's return value? Since Result
implements IntoFuture
, it's somewhat common to accidentally do something like foo.select2(Timeout::new(timeout))
, which compiles but immediately resolves rather than actually waiting on the timeout.
impl Stream for Interval { .. } | ||
``` | ||
|
||
These functions will lazily initialize a dedicated timer thread. We will eventually |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems a bit unfortunate we'd need to dedicate a thread to this rather than leaning on epoll's timeout field like is done now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #2 (comment)
That said, the new design allows running timers backed by epoll_wait. It just isn't the default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will the current same-thread heap-based timer infrastructure be kept somewhere (possibly deprecated) or dropped/reimplemented on top of a timer thread? Will we need to write our own timer heap to have same-thread timers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's also my only remaining worry. While the situation is cleared up around the reactor and executor threads (and should cover my use cases), having the default timer implementation automatically spawn a thread still is a problem. Anything using timers would uncontrollably spawn a thread without having a way to override that right now.
See also @alexcrichton 's comment here (the part about timers).
Apart from that I have no further worries/objections with the new version of the design.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It certainly makes sense as a default, yes. Thanks for confirming that this will be part of the refactoring of futures-timer, nothing else to add from my side in that case and I'm quite happy with the changes 👍
FWIW, my worry is less about having it as a separate thread (which indeed makes sense in the majority of situations, just like the reactor/executor use different threads by default) but having no control over the lifetime (and usage) of that thread.
tokio-reform.md
Outdated
### `tokio-io` | ||
|
||
The `tokio-io` crate needs an overall API audit. Its APIs may eventually be | ||
*re*exported within the `tokio` crate, but it also has value as a standalone |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The *
s here are messing up the markdown formatting downstream
tokio-reform.md
Outdated
|
||
impl Future for Timeout { .. } | ||
|
||
impl Interval { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a function range(min: Duration, max: Duration) that does the same as in my pr tokio-rs/tokio-timer#33?
I use this interval in a project where I want to contact a server, but as we have multiple thousand devices, not all devices should connect at the same time. So, this range brings some randomness into the wait time for a new connection attempt.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I also use random intervals all the time, it's too specialized. For example, your PR makes a default/uniform distribution for the interval, but I would say it should rather be normal/gaussian distribution to make interval more regular (or maybe there is some better random distribution for the specific use case of intervals?)
I'm still not sure about the global default handles. It's better than before but it's still black-magic-behind-the-scene-fuckery anti pattern, but in practice it would work. The biggest problem i have right now is that some hypothetical new project will simply leave out the signature with the handle variant:
The workaround would be to "just set the default" if i understand the RFC correctly. IMO it would be more elegant from a newcomer's perspective to see "Simple" or "Auto" newtypes variants that use the default handle. That way , somebody who is exploring the inner workings would immediately be told by the code: " To make it easier for beginners we provide a global handle. But if you want to create something similar, you should take a handle as an argument and wrap it with a "Simple" newtype like this". Anyways. Awesome project and keep up the good work. |
Can we make spawn take any future?
We're doing something similar with crossbeam defer(). It's a bit annoying to massage the futures in order to make spawn happy. |
not sure how useful this is, but I was working on the idea of global event loops here (modelled on seastar), before I ran out of steam: https://github.com/jkozlowski/tokio-smp. It indeed greatly simplifies the code. I was definitely thinking of epoll driven timers, but also smp message passing between cores... I am definitely liking the focus on simplification +1 |
tokio-reform.md
Outdated
) -> Self; | ||
|
||
fn tokio_reactor(&mut self) -> &mut reactor::Reactor; | ||
fn task_runner(&mut self) -> &mut current_thread::TaskRunner; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this may be an old remnant from a previous iteration, and I think that additionally we won't be able to provide Handle::spawner
below with the RFC as-is. I think it may be ok to remove these, though? I figured that the Core::tokio_reactor
and Handle::tokio_handle
methods are pretty important, but should we also figure out how to retain methods like Core::task_runner
, Handle::spawner
, and Core::from_tokio
?
tokio-reform.md
Outdated
|
||
- Uses of `Remote`/`Handle` that don't involve spawning threads can use the new | ||
`Handle`. | ||
- Local task spawning should migrate to use the `current_thread` module. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think current_thread
here should be thread
and/or Spawner
tokio-reform.md
Outdated
This API should be used in functions like `block_until` that enter executors, | ||
i.e. that block until some future completes (or other event | ||
occurs). Consequently, nested uses of `TaskRunner`, or usage of | ||
`current_thread::block_until` within a `TaskRunner` or thread pool, will panic, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this sentence wants to get updated to say that nested usage of block_until
or block_on_all
will panic (no more TaskRunner
)
tokio-reform.md
Outdated
`run` and `remote` methods and the `Executor` implementation: | ||
|
||
```rust | ||
impl<'a> From<&'a Reactor> for NotifyHandle { /* ... */ } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was it intended to leave this in with the addition of the wakeup
method? (seems fine to me to remove it for now to be as conservative as possible)
I've pushed updates:
I think the main remaining issue is that the RFC, as it stands, does not provide any way to override the default timer thread. I'm trying to punt on that for the moment, in part because @carllerche believes we probably want to tweak the overall API. So I'd like to take the |
@3n-mb Again, there is no reason for Tokio to add any "rx" concepts. futures-rs provides all the building blocks to build your own higher level abstractions that are compatible with the ecosystem. If you want to see rx concepts happen, the quickest strategy is to implement it yourself. |
@seanmonstar & @carllerche this thread explains why we talk rx here: First, someone is looking for a standardized reactive lib, i.e. lib done like it is done in other languages, facilitating language-neutral structuring of an app. Then, invariably, there will be an answer like:
But non-standard approach in tokio will bite you hard. |
@3n-mb once again, Tokio is only for I/O. futures-rs provides the asynchronous building blocks. Everything rx related can be built on top of futures-rs. I would appreciate it if the rx related discussion could move to the forum or an issue on the futures-rs repo. |
@carllerche can you put in docs that
Thank you. |
@eyoung @mathstuf |
I'd like to reference my question: tokio-rs/tokio-proto#202 |
I'm going to merge this. Most of the work has already happened in the tokio crate. |
is there a rough ETA on the work settling? Will this be blocked on futures 0.2? |
ok, found an answer to futures question here: https://github.com/cramertj/futures-rfcs/blob/futures-0.2/futures-02.md#guide-level-explanation |
No, the changes described in this RFC are not blocked on futures 0.2. The tokio reform changes will be pushed to crates.io very soon. There are a set of breaking changes in Tokio that require coordinating version releases. Specifically, breaking changes in mio, tokio-io, bytes, and iovec. Those will be coordinated with futures 0.2. |
Is there any documentation for migrating from
|
@asomers I believe in that case you can use https://docs.rs/futures/0.1.18/futures/sync/oneshot/fn.spawn.html |
@GoldenBadger carllerche had a different idea: |
There will also be |
Has there been any discussion of a way to spawn non- |
@joshlf You could use |
Hmm interesting thought; I'll try that. Thanks! Is there a reason that |
@joshlf The executor is a trait object, and its lifetime is unknown. |
@joshlf currently, the thread pool included with the futures crate does this (futures outlive the executor). |
Related: rust-lang/futures-rs#853 |
OK, thanks for the clarification. |
As one common concern with the default runtime was that there's no control anymore (just some magic thing happening in the background, which it is actually not in the current implementation: you explicitly create a runtime), and implementing a fully single-threaded solution becomes impossible, I've some example here (that was written as a testcase for a performance problem) for future reference. It was not entirely obvious to me from just reading the documentation and required reading the tokio code. This basically explicitly creates something like the default runtime with a configurable number of threads and runs a future on it, this does the same but completely single-threaded ( Note: there's no shutdown code, no error handling, no spawning of additional futures in here but that can easily be added. Take a look at the tokio |
I would recommend discontinuing discussion here and instead moving to issues on http://github.com/tokio-rs/tokio. |
Rendered
This RFC proposes to simplify and focus the Tokio project, in an attempt to make
it easier to learn and more productive to use. Specifically:
Add a default global event loop, eliminating the need for setting up and
managing your own event loop in the vast majority of cases.
Moreover, remove the distinction between
Handle
andRemote
by makingHandle
bothSend
andSync
and deprecatingRemote
. Thus, even workingwith custom event loops becomes simpler.
Allow swapping out this default event loop for those who want to exercise
full control.
Decouple all task execution functionality from Tokio, instead providing it
through a standard futures component.
When running tasks thread-locally (for non-
Send
futures),provide more fool-proof APIs that help avoid lost wakeups.
Eventually provide some default thread pools as well (out of scope for this
RFC).
Similarly, decouple timer futures from Tokio, providing functionality instead
through a new
futures-timer
crate.Provide the above changes in a new
tokio
crate, which is a slimmed downversion of today's
tokio-core
, and may eventually re-export the contentsof
tokio-io
. Thetokio-core
crate is deprecated, but will remain availablefor backward compatibility. In the long run, most users should only need to
depend on
tokio
to use the Tokio stack.Focus documentation primarily on
tokio
, rather than ontokio-proto
. Provide a much more extensive set of cookbook-style examplesand general guidelines, as well as a more in-depth guide to working with
futures.
Altogether, these changes, together with async/await, should go a long
distance toward making Tokio a newcomer-friendly library.
Rendered