Почему `tokio :: main` сообщает об ошибке" цикл обнаружен при обработке "? - PullRequest
2 голосов
/ 11 декабря 2019

Я использую Tokio и async / .await для создания UDP-сервера, где я могу получать и отправлять данные асинхронным способом.

SendHalf моего сокета UDP используется несколькими задачами. Для этого я использую Arc<Mutex<SendHalf>>. Вот почему существует Arc<Mutex<_>>.

use tokio::net::UdpSocket;
use tokio::net::udp::SendHalf;
use tokio::sync::mpsc;
use std::sync::{Arc, Mutex};
use std::net::SocketAddr;

struct Packet {
    sender: Arc<Mutex<SendHalf>>,
    buf: [u8; 512],
    addr: SocketAddr,
}

#[tokio::main]
async fn main() {
    let server = UdpSocket::bind(("0.0.0.0", 44667)).await.unwrap();
    let (mut server_rx, mut server_tx) = server.split();
    let sender = Arc::new(Mutex::new(server_tx));
    let (mut tx, mut rx) = mpsc::channel(100);

    tokio::spawn(async move {
        loop {
            let mut buffer = [0; 512];
            let (_, src) = server_rx.recv_from(&mut buffer).await.unwrap();
            let packet = Packet {
                sender: sender.clone(),
                buf: buffer,
                addr: src,
            };
            tx.send(packet).await;
        }
    });

    while let Some(packet) = rx.recv().await {
        tokio::spawn(async move {
            let mut socket = packet.sender.lock().unwrap();
            socket.send_to(&packet.buf, &packet.addr).await.unwrap();
        });
    }
}

Здесь также находится Детская площадка .

Я сталкиваюсь с ошибкой компилятора, которую не понимаю:

error[E0391]: cycle detected when processing `main`
  --> src/main.rs:13:1
   |
13 | #[tokio::main]
   | ^^^^^^^^^^^^^^
   |
note: ...which requires processing `main::{{closure}}#0::{{closure}}#1`...
  --> src/main.rs:34:33
   |
34 |           tokio::spawn(async move {
   |  _________________________________^
35 | |             let mut socket = packet.sender.lock().unwrap();
36 | |             socket.send_to(&packet.buf, &packet.addr).await.unwrap();
37 | |         });
   | |_________^
   = note: ...which again requires processing `main`, completing the cycle
note: cycle used when processing `main::{{closure}}#0`
  --> src/main.rs:13:1
   |
13 | #[tokio::main]
   | ^^^^^^^^^^^^^^

Почему мой код создает цикл? Почему вызов требует обработки main?

Что означает ошибка более подробно? Я хочу понять, что происходит.

1 Ответ

3 голосов
/ 11 декабря 2019

Согласно документации tokio, когда дело доходит до с использованием значения !Send из задачи :

Удержание значения !Send при вызовах .await приведет к сообщению об ошибке недружественной компиляции, похожему на:

[... some type ...] cannot be sent between threads safely

или:

error[E0391]: cycle detected when processing main

Высвидетелем этой точной ошибки. Когда вы блокируете Mutex:

pub fn lock(&self) -> LockResult<MutexGuard<T>>

, возвращается MutexGuard, то есть !Send:

impl<'_, T: ?Sized> !Send for MutexGuard<'_, T>

Это прекрасно компилируется:

#[tokio::main]
async fn main() {
    ...

    while let Some(packet) = rx.recv().await {
        let mut socket = packet.sender.lock().unwrap();
        socket.send_to(&packet.buf, &packet.addr).await.unwrap();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...