我有一个启动工作线程的线程,所有线程都应该永远存在.每个工作线程都维护着自己的Sockets 列表.
有些操作要求我遍历当前活动的所有套接字,但是我在尝试创建包含指向另一个列表所拥有的套接字的指针的套接字的主列表时遇到了麻烦.
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);
}
Run Code Online (Sandbox Code Playgroud)
我收到的错误......
error[E0477]: the type `[closure@src/main.rs:107:34: 107:86 tx:std::sync::mpsc::Sender<std::net::TcpStream>, rx:std::sync::mpsc::Receiver<std::net::TcpStream>, master_socket_list:std::sync::Arc<std::sync::Mutex<mastersocketlist::MasterSocketList<'_>>>]` does not fulfill the required lifetime
--> src/main.rs:107:20
|
107 | let prox = thread::spawn(move || Slot::event_loop(tx, rx, master_socket_list));
| ^^^^^^^^^^^^^
|
= note: type must outlive the static lifetime
Run Code Online (Sandbox Code Playgroud)
我甚至不知道我所尝试的是否可以作为安全代码.
我希望mastersocketlist包含一个指向套接字的指针,其中套接字的生命周期由创建它的线程定义.我相信所有这些错误都意味着什么,但我不知道如何提供适当的生命周期注释来解决它.
She*_*ter 26
关于Rust的一个好处是跨函数的类型检查完全由函数签名完成.这意味着您可以用函数替换大多数函数体unimplemented!()并保留类型检查错误.
重复这个过程几次,你最终没有调用很多函数 - 删除它们.内联模块和减少结构/枚举也可以提供帮助.
在某些时候,你的错误将消失 - 这是问题的第一个线索!坚持下去,你会得到一个小小的再现:
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() {}
Run Code Online (Sandbox Code Playgroud)
检查错误,它仍然匹配:
error[E0477]: the type `[closure@src/main.rs:12:23: 14:10 master_socket_list:std::sync::Arc<std::sync::Mutex<MasterSocketList<'a>>>]` does not fulfill the required lifetime
--> src/main.rs:12:9
|
12 | thread::spawn(move || {
| ^^^^^^^^^^^^^
|
= note: type must satisfy the static lifetime
Run Code Online (Sandbox Code Playgroud)
让我们检查文档的签名thread::spawn:
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
Run Code Online (Sandbox Code Playgroud)
这里的关键点是F: Send + 'static- 你给出的闭包spawn 必须只包含持续程序整个生命周期的引用.这是因为spawn可以创建分离的线程.一旦分离,线程可以永远存在,所以所有引用必须至少存活那么长,否则你会得到悬空引用,这是一件坏事!Rust再次拯救了这一天!
如果要保证线程将在已知点终止,则可以使用作用域线程,例如scoped-threadpool或crossbeam提供的线程.
如果你的代码里面没有一个带有生命周期的变量,那么使用某种类型的共享所有权,比如Arc配合一些东西来保证只有一个线程可以改变变量,就像Mutex已经足够了.这允许每个线程拥有共享值,最后在最后一个线程退出时丢弃它.请参阅如何在线程之间共享可变对象?详情.
| 归档时间: |
|
| 查看次数: |
3600 次 |
| 最近记录: |