创建连接到共享状态的循环Tokio流

时间:2019-07-18 14:46:38

标签: rust stream rust-tokio

我遇到了一个我不太了解和希望的问题 也许有人可以看到我误解的东西。

问题很简单:我有一个全局状态(共享 并希望在一个任务上有一个无限循环 向量处于全局状态。然后我将以一定的间隔压缩 流并因此定期发射下一个值 流。

如果状态中的向量发生变化,则无限流应仅 重新加载向量并开始从新的向量开始读取,以及 丢弃旧数组。

这是到目前为止我得到的代码,问题在 帖子的结尾。

use futures::stream::Stream;
use futures::{Async, Poll};
use std::iter::Cycle;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use tokio::timer::Interval;

我们定义一个全局状态,该状态包含一个可以为 更新。每当阵列更新时,我们都会逐步更新版本并 设置数组。

struct State<T> {
    version: u32,
    array: Vec<T>,
}

impl<T> State<T> {
    fn new(array: Vec<T>) -> Self {
        Self {
            version: 0,
            array: Vec::new(),
        }
    }

    fn update(&mut self, array: Vec<T>) {
        self.version += 1;
        self.array = array;
    }
}

现在,我们在状态上创建一个流。初始化后,它将 从状态读取数组和版本并存储,然后保留 内部std::iter::Cycle的实例将在 数组。

struct StateStream<I> {
    state: Arc<Mutex<State<I::Item>>>,
    version: u32,
    iter: Cycle<I>,
}

impl<I> StateStream<I>
where
    I: Iterator,
{
    fn new(state: Arc<Mutex<State<I::Item>>>) -> Self {
        let (version, array) = {
            let locked_state = state.lock().unwrap();
            (locked_state.version, locked_state.array)
        };

        Self {
            state: state,
            version: version,
            iter: array.iter().cycle(),
        }
    }
}   

我们现在为StateStream实现流。每次民意调查 将检查状态的版本是否已更改,如果已更改,请重新加载 数组和版本。

然后,我们将从迭代器中获取下一项,并将其返回。

impl<I> Stream for StateStream<I>
where
    I: Iterator + Clone,
{
    type Item = I::Item;
    type Error = ();

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let locked_state = self.state.lock().unwrap();
        if locked_state.version > self.version {
            self.iter = locked_state.array.clone().iter().cycle();
            self.version = locked_state.version;
        }
        Ok(Async::Ready(self.iter.next()))
    }
}

主程序如下所示。我不在这里更新向量,但是 这对于眼前的案件并不重要。

fn main() {
    let state = Arc::new(Mutex::new(State::new(vec![2, 3, 5, 7, 11, 13])));
    let primes = StateStream::new(state)
        .take(20)
        .zip(
            Interval::new(Instant::now(), Duration::from_millis(500))
                .map_err(|err| println!("Error: {}", err)),
        )
        .for_each(|(number, instant)| {
            println!("fire; number={}, instant={:?}", number, instant);
            Ok(())
        });
    tokio::run(primes);
}

编译时,出现以下错误:

cargo run --example cycle_stream_shared
   Compiling tokio-testing v0.1.0 (/home/mats/crates/tokio-examples)
error[E0308]: mismatched types
  --> examples/cycle_stream_shared.rs:66:19
   |
66 |             iter: array.iter().cycle(),
   |                   ^^^^^^^^^^^^^^^^^^^^ expected type parameter, found struct `std::slice::Iter`
   |
   = note: expected type `std::iter::Cycle<I>`
              found type `std::iter::Cycle<std::slice::Iter<'_, <I as std::iter::Iterator>::Item>>`

error[E0308]: mismatched types
  --> examples/cycle_stream_shared.rs:81:25
   |
81 |             self.iter = locked_state.array.clone().iter().cycle();
   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found struct `std::slice::Iter`
   |
   = note: expected type `std::iter::Cycle<I>`
              found type `std::iter::Cycle<std::slice::Iter<'_, <I as std::iter::Iterator>::Item>>`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0308`.
error: Could not compile `tokio-testing`.

To learn more, run the command again with --verbose.

现在,错误和解释说具体类型不是 可能派生,但在这种情况下,我使用的是通用结构 Cycle<I>,并期望将I实例化为std::slice::Iter<'_, I::Item>。由于std::slice::Iter实现了Iterator并且该类型实现了所有必需的特征以进行匹配。

存在一些类似问题的答案,但似乎没有 匹配这种情况:

其他问题主要是指这两个或变体 这些。

更新:将其更改为通用类型,以证明它仍然无法正常工作。

0 个答案:

没有答案