Rust 如何在同一资源上链接两个期货,而不必提前定义每个方法组合?

Rust 如何在同一资源上链接两个期货,而不必提前定义每个方法组合?,rust,Rust,我正在编写引导代码,并使用SIM800L调制解调器连接到2G/3G网络。这个调制解调器与一个串行通道连接,我在这个项目之外将它多路复用成4个通道:数据、文本接口、控制接口和状态消息 为了引导它,我需要运行一系列顺序命令。此顺序根据调制解调器的输出而改变SIM卡是否已锁定?SIM卡需要解锁哪些类型的信息?我们在搞什么APN?我们需要什么样的网络选择?。我最初认为,这将是一个完美的未来应用程序,因为每个单独的操作在+COPS(其中一个命令)上的空闲时间可能非常昂贵,返回需要10秒 我开始讨论类似这样

我正在编写引导代码,并使用SIM800L调制解调器连接到2G/3G网络。这个调制解调器与一个串行通道连接,我在这个项目之外将它多路复用成4个通道:数据、文本接口、控制接口和状态消息

为了引导它,我需要运行一系列顺序命令。此顺序根据调制解调器的输出而改变SIM卡是否已锁定?SIM卡需要解锁哪些类型的信息?我们在搞什么APN?我们需要什么样的网络选择?。我最初认为,这将是一个完美的未来应用程序,因为每个单独的操作在+COPS(其中一个命令)上的空闲时间可能非常昂贵,返回需要10秒

我开始讨论类似这样的东西,虽然它编译并似乎按顺序执行命令,但第三个操作是空的。我的问题有两个:为什么运行的命令不会在最后一次的结果中弹出,并且有没有一种更健壮的方法来执行类似的操作

#![feature(conservative_impl_trait)]

extern crate futures;
extern crate tokio_core;

use std::sync::{Arc, Mutex};
use futures::{future, Future};
use tokio_core::reactor::Core;
use futures::sync::oneshot;
use std::thread;
use std::io;
use std::time::Duration;

pub struct Channel {
    operations: Arc<Mutex<Vec<String>>>,
}

impl Channel {
    pub fn ops(&mut self) -> Box<Future<Item = Vec<String>, Error = io::Error>> {
        println!("{:?}", self.operations);
        let ops = Arc::clone(&self.operations);
        let ops = ops.lock().unwrap();
        future::ok::<Vec<String>, io::Error>(ops.to_vec()).boxed()
    }

    pub fn run(&mut self, command: &str) -> Box<Future<Item = Vec<String>, Error = io::Error>> {
        let (tx, rx) = oneshot::channel::<Vec<String>>();

        let ops = Arc::clone(&self.operations);
        let str_cmd = String::from(command);
        thread::spawn(move || {
            thread::sleep(Duration::new(0, 10000));

            let mut ops = ops.lock().unwrap();
            ops.push(str_cmd.clone());
            println!("Pushing op: {}", str_cmd.clone());
            tx.send(vec!["OK".to_string()])
        });

        rx.map_err(|_| io::Error::new(io::ErrorKind::NotFound, "Test"))
            .boxed()
    }
}

pub struct Channels {
    inner_object: Arc<Mutex<Channel>>,
}

impl Channels {
    pub fn one(&self, cmd: &str) -> Box<Future<Item = Vec<String>, Error = io::Error>> {
        let v = Arc::clone(&self.inner_object);
        let mut v = v.lock().unwrap();
        v.run(&cmd)
    }

    pub fn ops(&self) -> Box<Future<Item = Vec<String>, Error = io::Error>> {
        let v = Arc::clone(&self.inner_object);
        let mut v = v.lock().unwrap();
        v.ops()
    }

    pub fn run_command(&self) -> Box<Future<Item = (), Error = io::Error>> {
        let a = self.one("AT+CMEE=2");
        let b = self.one("AT+CREG=0");
        let c = self.ops();
        Box::new(a.and_then(|result_1| {
            assert_eq!(result_1, vec![String::from("OK")]);
            b.and_then(|result_2| {
                assert_eq!(result_2, vec![String::from("OK")]);
                c.map(move |ops| {
                    assert_eq!(
                        ops.as_slice(),
                        ["AT+CMEE=2".to_string(), "AT+CREG=0".to_string()]
                    );
                })
            })
        }))
    }
}

fn main() {
    let mut core = Core::new().expect("Core should be created");
    let channels = Channels {
        inner_object: Arc::new(Mutex::new(Channel {
            operations: Arc::new(Mutex::new(vec![])),
        })),
    };
    let result = core.run(channels.run_command()).expect("Should've worked");

    println!("{:?}", result);
}
为什么运行的命令不会在最后的结果中弹出

因为您没有按顺序安排操作以这种方式发生:

let a = self.one("AT+CMEE=2");
let b = self.one("AT+CREG=0");
let c = self.ops();
这将立即建立:

a、 承诺在他们做出反应之前先睡一会儿 c-承诺在向量中得到ops 在创建c时,休眠尚未终止,因此没有执行任何操作,因此向量将为空

Future::and_则用于定义顺序操作。这在您的案例中是复杂的,因为您希望在and_然后闭包的主体中使用self。您可以克隆弧并使用它

你会注意到我做了一些简化:

返回字符串而不是Vec 删除未使用的mut限定符和互斥体 直接返回操作Vec。
您的真实频道是否实际跟踪所有发送的操作?或者它更接近你读写的串行端口?@Shepmaster这就是事情变得有趣的地方。实际上,真正的串行通道跟踪两种特殊操作,它们对应于模式开关。您可以将每个mux通道切换到PDU或文本模式,从而打开完全不同的命令集。幸运的是,其余的没有被追踪。至于操作,其中一些可以也将失败。例如,在查询SIM卡状态时,SIMlock被认为是一个错误!然而,我猜想,正如您的初始指针所覆盖的那样,我将能够充分利用或利用其他功能。@Shepmaster我无法在同一通道上并行执行命令,这主要是由于底层协议的原因-我无法跟踪什么时候/什么时候应答,只是应答发生了。因此,很遗憾,它一直都是顺序操作。非常感谢您的帮助和详细解释:-
extern crate futures;
extern crate tokio_core;

use std::sync::{Arc, Mutex};
use futures::Future;
use tokio_core::reactor::Core;
use futures::sync::oneshot;
use std::thread;
use std::io;
use std::time::Duration;

pub struct Channel {
    operations: Arc<Mutex<Vec<String>>>,
}

impl Channel {
    fn ops(&self) -> Vec<String> {
        self.operations.lock().unwrap().clone()
    }

    fn command(&self, command: &str) -> Box<Future<Item = String, Error = io::Error>> {
        let (tx, rx) = oneshot::channel();

        let ops = Arc::clone(&self.operations);
        let str_cmd = String::from(command);

        thread::spawn(move || {
            thread::sleep(Duration::new(0, 10000));

            println!("Pushing op: {}", str_cmd);
            ops.lock().unwrap().push(str_cmd);

            tx.send("OK".to_string())
        });

        Box::new(rx.map_err(|_| io::Error::new(io::ErrorKind::NotFound, "Test")))
    }
}

struct Channels {
    data: Arc<Channel>,
}

impl Channels {
    fn run_command(&self) -> Box<Future<Item = (), Error = io::Error>> {
        let d2 = Arc::clone(&self.data);
        let d3 = Arc::clone(&self.data);

        Box::new(
            self.data
                .command("AT+CMEE=2")
                .and_then(move |cmee_answer| {
                    assert_eq!(cmee_answer, "OK"); // This should be checked in `command` and be a specific Error
                    d2.command("AT+CREG=0")
                })
                .map(move |creg_answer| {
                    assert_eq!(creg_answer, "OK"); // This should be checked in `command` and be a specific Error
                    let ops = d3.ops();
                    assert_eq!(ops, ["AT+CMEE=2", "AT+CREG=0"])
                }),
        )
    }
}

fn main() {
    let mut core = Core::new().expect("Core should be created");
    let channels = Channels {
        data: Arc::new(Channel {
            operations: Arc::new(Mutex::new(vec![])),
        }),
    };
    let result = core.run(channels.run_command()).expect("Should've worked");

    println!("{:?}", result);
}
extern crate futures;
extern crate tokio_core;

use std::sync::{Arc, Mutex};
use futures::Future;
use tokio_core::reactor::Core;
use futures::sync::oneshot;
use std::thread;
use std::io;
use std::time::Duration;

#[derive(Clone)]
pub struct Channel {
    operations: Arc<Mutex<Vec<String>>>,
}

impl Channel {
    fn ops(&self) -> Arc<Mutex<Vec<String>>> {
        Arc::clone(&self.operations)
    }

    fn command(self, command: &str) -> Box<Future<Item = (Self, String), Error = io::Error>> {
        let (tx, rx) = oneshot::channel();
        let str_cmd = String::from(command);

        thread::spawn(move || {
            thread::sleep(Duration::new(0, 10000));

            println!("Pushing op: {}", str_cmd);
            self.operations.lock().unwrap().push(str_cmd);

            tx.send((self, "OK".to_string()))
        });

        Box::new(rx.map_err(|_| io::Error::new(io::ErrorKind::NotFound, "Test")))
    }
}

struct Channels {
    data: Channel,
}

impl Channels {
    fn run_command(self) -> Box<Future<Item = (), Error = io::Error>> {
        Box::new(
            self.data
                .clone()
                .command("AT+CMEE=2")
                .and_then(|(channel, cmee_answer)| {
                    assert_eq!(cmee_answer, "OK");
                    channel.command("AT+CREG=0")
                })
                .map(|(channel, creg_answer)| {
                    assert_eq!(creg_answer, "OK");
                    let ops = channel.ops();
                    let ops = ops.lock().unwrap();
                    assert_eq!(*ops, ["AT+CMEE=2", "AT+CREG=0"]);
                }),
        )
    }
}

fn main() {
    let mut core = Core::new().expect("Core should be created");
    let channels = Channels {
        data: Channel {
            operations: Arc::new(Mutex::new(vec![])),
        },
    };
    let result = core.run(channels.run_command()).expect("Should've worked");

    println!("{:?}", result);
}