Rust 线程之间共享引用的生存期问题

Rust 线程之间共享引用的生存期问题,rust,lifetime,Rust,Lifetime,我有一个线程可以启动工作线程,所有线程都将永远存在。每个工作线程维护自己的Sockets列表 有些操作要求遍历当前处于活动状态的所有套接字,但我在尝试创建包含指向另一个列表所拥有的套接字的指针的套接字主列表时遇到了问题 use std::{str, thread}; use std::thread::JoinHandle; use std::io::{Read, Write}; use std::net::{TcpListener, TcpStream}; use std::sync::{Arc

我有一个线程可以启动工作线程,所有线程都将永远存在。每个工作线程维护自己的
Socket
s列表

有些操作要求遍历当前处于活动状态的所有套接字,但我在尝试创建包含指向另一个列表所拥有的套接字的指针的套接字主列表时遇到了问题

use std::{str, thread};
use std::thread::JoinHandle;
use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};
use std::sync::{Arc, Mutex};
use std::ops::DerefMut;
use std::sync::mpsc::{channel, Sender, Receiver, TryRecvError};
use self::socketlist::SocketList;
use self::mastersocketlist::MasterSocketList;

pub struct Socket {
    user: String,
    stream: TcpStream,
}

mod socketlist {
    use self::SocketList::{Node, End};
    use super::Socket;

    pub enum SocketList {
        Node(Socket, Box<SocketList>),
        End,
    }

    impl SocketList {
        pub fn new() -> SocketList {
            End
        }

        pub fn add(self, socket: Socket) -> SocketList {
            Node(socket, Box::new(self))
        }

        pub fn newest<'a>(&'a mut self) -> Result<&'a Socket, String> {
            match *self {
                Node(ref mut socket, ref mut next) => Ok(socket),
                End => Err("No socket available".to_string()),
            }
        }
    }
}

mod mastersocketlist {
    use self::MasterSocketList::{Node, End};
    use super::Socket;

    pub enum MasterSocketList<'a> {
        Node(Box<&'a Socket>, Box<MasterSocketList<'a>>),
        End,
    }

    impl<'a> MasterSocketList<'a> {
        pub fn new() -> MasterSocketList<'a> {
            End
        }

        pub fn add(self, socket: &'a Socket) -> MasterSocketList<'a> {
            MasterSocketList::Node(Box::new(&socket), Box::new(self))
        }
    }
}

pub struct SlotManager {
    prox: JoinHandle<()>,
    prox_tx: Sender<TcpStream>,
}

impl SlotManager {
    pub fn new() -> SlotManager {
        let (tx, rx): (Sender<TcpStream>, Receiver<TcpStream>) = channel();

        let tx_clone = tx.clone();
        let prox = thread::spawn(move || SlotManager::event_loop(tx, rx));

        SlotManager {
            prox: prox,
            prox_tx: tx_clone,
        }
    }

    pub fn sender(&self) -> Sender<TcpStream> {
        self.prox_tx.clone()
    }

    fn event_loop(tx: Sender<TcpStream>, rx: Receiver<TcpStream>) {
        let socket_list = Arc::new(Mutex::new(MasterSocketList::new()));
        let mut slot = Slot::new(socket_list.clone());
        loop {
            match rx.try_recv() {
                Ok(stream) => slot.new_connection(stream),
                Err(e) => {}
            }
        }
    }
}

pub struct Slot {
    prox: JoinHandle<()>,
    prox_tx: Sender<TcpStream>,
}

impl Slot {
    pub fn new(master_socket_list: Arc<Mutex<MasterSocketList>>) -> Slot {
        let (tx, rx): (Sender<TcpStream>, Receiver<TcpStream>) = channel();

        let tx_clone = tx.clone();
        let prox = thread::spawn(move || Slot::event_loop(tx, rx, master_socket_list));

        Slot {
            prox: prox,
            prox_tx: tx_clone,
        }
    }

    pub fn new_connection(&self, stream: TcpStream) {
        self.prox_tx.send(stream);
    }

    fn event_loop(tx: Sender<TcpStream>,
                  rx: Receiver<TcpStream>,
                  master_socket_list: Arc<Mutex<MasterSocketList>>) {

        let mut sockets = SocketList::new();
        loop {
            // Check for new connections
            match rx.try_recv() {
                Ok(stream) => {
                    let mut socket = Socket {
                        user: "default".to_string(),
                        stream: stream,
                    };
                    sockets = sockets.add(socket);

                    let mut msl_guard = match master_socket_list.lock() {
                        Ok(guard) => guard,
                        Err(poisoned) => poisoned.into_inner(),
                    };
                    let mut msl_handle = msl_guard.deref_mut();
                    *msl_handle = msl_handle.add(sockets.newest().unwrap());
                }
                Err(e) => {}
            }
        }
    }
}

fn main() {
    let mut slot_manager = SlotManager::new();
    let listener = TcpListener::bind("127.0.0.1:1234").unwrap();
    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                let sender = slot_manager.sender();
                thread::spawn(move || {
                    sender.send(stream);
                    //process_new_connection(stream, sender)
                });
            }
            Err(e) => println!("Connection error: {}", e),
        }
    }
    drop(listener);
}
使用std:{str,thread};
使用std::thread::JoinHandle;
使用std::io::{Read,Write};
使用std::net::{TcpListener,TcpStream};
使用std::sync::{Arc,Mutex};
使用std::ops::DerefMut;
使用std::sync::mpsc:{channel,Sender,Receiver,TryRecvError};
使用self::socketlist::socketlist;
使用self::mastersocketlist::mastersocketlist;
发布结构套接字{
用户:字符串,
流:TcpStream,
}
mod socketlist{
使用self::SocketList::{Node,End};
使用super::Socket;
发布枚举套接字列表{
节点(插座、盒),
完,,
}
impl SocketList{
pub fn new()->SocketList{
终点
}
pub fn add(self,socket:socket)->SocketList{
节点(套接字、框::新建(自))
}
最新结果{
节点(框>),
完,,
}
恳求{
pub fn new()->MasterSocketList MasterSocketList>]`未满足所需的生存期
-->src/main.rs:107:20
|
107 | let prox=thread::spawn(移动| |插槽::事件循环(发送、接收、主插槽列表));
|                    ^^^^^^^^^^^^^
|
=注意:类型必须超过静态生存期
我甚至不知道我所尝试的是否是安全代码


我希望
mastersocketlist
包含一个指向套接字的指针,其中套接字的生存期由创建它的线程定义。我相信这就是所有这些错误的含义,但我不知道如何提供正确的生存期注释来修复它。

关于生锈的一个好处是跨函数的类型检查是有效的仅由函数签名完成。这意味着您可以用
未实现!()
替换大多数函数体,并保留类型检查错误

重复这个过程几次,你就不会调用太多的函数——删除那些函数。内联模块和减少结构/枚举也会有所帮助

在某个时刻,你的错误会消失——这是问题的第一条线索!坚持下去,你会得到一个微小的复制品:

use std::sync::{Arc, Mutex};
use std::thread;

pub enum MasterSocketList<'a> {
    One(&'a u8),
}

pub struct Slot;

impl Slot {
    pub fn new<'a>(master_socket_list: Arc<Mutex<MasterSocketList<'a>>>) -> Slot {
        thread::spawn(move || {
            master_socket_list;
        });
        unimplemented!();
    }
}

fn main() {}
这里的关键点是
F:Send+'static
-您给
spawn
的闭包必须只包含持续整个程序生命周期的引用。这是因为
spawn
可以创建分离的线程。分离后,线程可以永远存在,因此所有引用都必须至少存在t帽子要长,否则你会得到悬挂的参考资料,这是一件坏事!生锈再一次拯救了这一天

如果要保证线程将在已知点终止,可以使用作用域线程,例如由或提供的线程


如果您的代码中没有一个生命周期内的变量,那么使用某种类型的共享所有权(如与确保只有一个线程可以变异变量的东西(如)配对就足够了。这允许每个线程拥有共享值,最后在最后一个线程退出时删除它。有关详细信息,请参阅。

Whoa,我不知道我可以把
未实现的()!
放在那里,让示例更清晰。非常感谢您的帮助!
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
where
    F: FnOnce() -> T,
    F: Send + 'static,
    T: Send + 'static,