Giter VIP home page Giter VIP logo

Comments (7)

vi avatar vi commented on June 5, 2024

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.

vi avatar vi commented on June 5, 2024

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.

cmichi avatar cmichi commented on June 5, 2024

@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.

vi avatar vi commented on June 5, 2024

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.

vi avatar vi commented on June 5, 2024

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.

vi avatar vi commented on June 5, 2024

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.

cmichi avatar cmichi commented on June 5, 2024

Thanks a lot, this answered my questions! I close the issue now.

from tokio-stdin-stdout.

Related Issues (1)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.