Comments (7)
ThreadStdout
is not clonable.
Use tokio_write_all(&mut stdout, "hello");
. Or Arc<Mutex<ThreadedStdout>>
/ Rc<RefCell<ThreadedStdout>>
if there are borrow/lifetime problems.
The example won't output anything anyway because by doing tokio_write_all
you don't output bytes to stdout. You plan the action of outputting the bytes to stdout. tokio::run
/ tokio::spawn
should be used to actually execute the plan.
tokio_io::io::shutdown(stdout)
should also be not neglected.
I'm trying to produce the actual example based on what you want.
from tokio-stdin-stdout.
Here is contrived looping example based on the code
extern crate tokio_io;
extern crate tokio_stdin_stdout;
extern crate tokio;
use tokio::prelude::Future;
use tokio_io::io::write_all as tokio_write_all;
use std::sync::{Mutex,Arc};
#[derive(Clone)]
struct RoamingStdout(Arc<Mutex<tokio_stdin_stdout::ThreadedStdout>>);
impl RoamingStdout {
fn new() -> RoamingStdout {
RoamingStdout(Arc::new(Mutex::new(tokio_stdin_stdout::stdout(0))))
}
}
impl std::io::Write for RoamingStdout {
fn write(&mut self, buf: &[u8]) -> std::result::Result<usize, std::io::Error> {
self.0.lock().unwrap().write(buf)
}
fn flush(&mut self) -> std::result::Result<(), std::io::Error> {
self.0.lock().unwrap().flush()
}
}
impl tokio_io::AsyncWrite for RoamingStdout {
fn shutdown(&mut self) -> std::result::Result<tokio::prelude::Async<()>, std::io::Error> {
self.0.lock().unwrap().shutdown()
}
}
fn main() {
let stdout = RoamingStdout::new();
let mut the_plan : Box<dyn Future<Item=(), Error=()> + Send> =
Box::new(tokio::prelude::future::ok(()));
for _ in 1..10 {
let stdout = stdout.clone();
the_plan = Box::new(the_plan.and_then(move |()| {
tokio_write_all(stdout, "hello\n").map(drop).map_err(drop)
}));
}
let shutdn = tokio_io::io::shutdown(stdout).map(drop).map_err(drop);
the_plan = Box::new(the_plan.and_then(|()|shutdn));
tokio::run(the_plan);
}
Note that is it not recommended way to do this. A linked list of futures is build in memory, and memory required is proportional to the number of loop iterations.
Shall helpers like RoamingStdout
be inside the library tokio-stdin-stdout
itself?
from tokio-stdin-stdout.
@vi Thanks a lot for the comprehensive answer, this was really helpful!
Note that is it not recommended way to do this.
What would be a recommended way? The scenario that I have is that I basically have a loop which spawns a chain of asynchronous operations and I want to write the result asynchronously to stdout
in the last future.
A linked list of futures is build in memory […]
Was there a reason why you didn't use something like tokio::spawn(the_plan)
in the loop instead of building a chain of futures and executing the chain at the end?
Shall helpers like RoamingStdout be inside the library tokio-stdin-stdout itself?
👍 I guess it would make the library easier to use for my scenario, I'm just not sure of how common this is.
from tokio-stdin-stdout.
What would be a recommended way?
I'd generated a stream of strings to output, then piped it into a sink that writes to stdout:
extern crate tokio_io;
extern crate tokio_stdin_stdout;
extern crate tokio;
use tokio::prelude::Future;
use tokio_io::io::write_all as tokio_write_all;
use std::sync::{Mutex,Arc};
use tokio::prelude::Stream;
#[derive(Clone)]
struct RoamingStdout(Arc<Mutex<tokio_stdin_stdout::ThreadedStdout>>);
impl RoamingStdout {
fn new() -> RoamingStdout {
RoamingStdout(Arc::new(Mutex::new(tokio_stdin_stdout::stdout(0))))
}
}
impl std::io::Write for RoamingStdout {
fn write(&mut self, buf: &[u8]) -> std::result::Result<usize, std::io::Error> {
self.0.lock().unwrap().write(buf)
}
fn flush(&mut self) -> std::result::Result<(), std::io::Error> {
self.0.lock().unwrap().flush()
}
}
impl tokio_io::AsyncWrite for RoamingStdout {
fn shutdown(&mut self) -> std::result::Result<tokio::prelude::Async<()>, std::io::Error> {
self.0.lock().unwrap().shutdown()
}
}
fn main() {
let stdout = RoamingStdout::new();
let stdout_ = stdout.clone();
let h = std::iter::repeat("hello\n").take(10);
let s = tokio::prelude::stream::iter_ok::<_,()>(h);
let f = s.for_each(move |x| {
tokio_write_all(stdout_.clone(), x).map(drop).map_err(drop)
});
let prog = f.and_then(move |()| {
tokio_io::io::shutdown(stdout.clone()).map(drop).map_err(drop)
});
tokio::run(prog);
}
I don't know your requirements, this hello loop example is too simple. Need more specifics to recommend some approach. Spawning solution also has advantages and drawbacks.
from tokio-stdin-stdout.
I guess it would make the library easier to use for my scenario, I'm just not sure of how common this is.
I'm going to implement and publish it anyway.
from tokio-stdin-stdout.
Published v0.1.4, with new functions.
Now the example is this:
extern crate tokio;
extern crate tokio_io;
extern crate tokio_stdin_stdout;
use tokio::prelude::Future;
use tokio_io::io::write_all as tokio_write_all;
use tokio::prelude::Stream;
fn main() {
let stdout = tokio_stdin_stdout::stdout(0).make_sendable();
let stdout_ = stdout.clone();
let h = std::iter::repeat("hello\n").take(10);
let s = tokio::prelude::stream::iter_ok::<_, ()>(h);
let f = s.for_each(move |x| tokio_write_all(stdout_.clone(), x).map(drop).map_err(drop));
let prog = f.and_then(move |()| {
tokio_io::io::shutdown(stdout.clone())
.map(drop)
.map_err(drop)
});
tokio::run(prog);
}
Alternative example without the mutex:
extern crate tokio;
extern crate tokio_io;
extern crate tokio_stdin_stdout;
use tokio::prelude::Future;
use tokio_io::io::write_all as tokio_write_all;
use tokio::prelude::Stream;
fn main() {
let stdout = tokio_stdin_stdout::stdout(0).make_clonable();
let stdout_ = stdout.clone();
let h = std::iter::repeat("hello\n").take(10);
let s = tokio::prelude::stream::iter_ok::<_, ()>(h);
let f = s.for_each(move |x| tokio_write_all(stdout_.clone(), x).map(drop).map_err(drop));
let prog = f.and_then(move |()| {
tokio_io::io::shutdown(stdout.clone())
.map(drop)
.map_err(drop)
});
tokio::executor::current_thread::block_on_all(prog).unwrap();
}
Close the issue if everyting's OK.
from tokio-stdin-stdout.
Thanks a lot, this answered my questions! I close the issue now.
from tokio-stdin-stdout.
Related Issues (1)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from tokio-stdin-stdout.