multithreading - 在线程中使用特征方法

标签 multithreading design-patterns rust

基本上,我正在制作一个程序,它正在监听一堆端口并以不同的方式处理传入的数据包。我决定将这段代码捆绑到一个特征中:

use std::old_io::{TcpStream, TcpListener, Listener, Acceptor, EndOfFile, IoResult};
use std::thread::Thread;

trait Server {
    fn new(port: u16) -> Self;

    fn hostname(&self) -> &String;

    fn initialize(&self) {
        let acceptor = TcpListener::bind(self.hostname().as_slice()).listen().unwrap();
        Thread::spawn(move|| {
            let mut acceptor = acceptor;
            for incoming_stream in acceptor.incoming() {
                match incoming_stream {
                    Ok(stream) => {
                        self.handle_client(stream);
                    },
                    Err(ref e) if e.kind == EndOfFile => break,
                    Err(e) => panic!("Unexpected error: {}", e),
                }
            }
        });
    }

    fn handle_client(&self, stream: TcpStream) -> ();
}

pub struct InternodeServer {
    hostname: String,
}

impl Server for InternodeServer {
    fn new(port: u16) -> InternodeServer {
        let hostname = format!("127.0.0.1:{}", port);
        InternodeServer {
            hostname: hostname,
        }
    }

    fn hostname(&self) -> &String {
        &self.hostname
    }

    fn handle_client(&self, stream: TcpStream) {
        println!("Received connection");
        let mut stream = stream;
        let response = b"Hello\r\n";
        let _ = stream.write_all(response);
        let _ = stream.close_write();
    }
}

fn main() {
    let test_server = <InternodeServer as Server>::new(9337);
    test_server.initialize();
}

但是,此代码将不起作用,因为您无法发送 Self。这是我收到的错误:

test.rs:11:9: 11:22 error: the trait `core::marker::Send` is not implemented for the type `Self` [E0277]
test.rs:11         Thread::spawn(move|| {
                   ^~~~~~~~~~~~~
test.rs:11:9: 11:22 note: `Self` cannot be sent between threads safely
test.rs:11         Thread::spawn(move|| {
                   ^~~~~~~~~~~~~

所以我也尝试将 handle_client 设为静态方法来避免 self.为此,我只是将 handle_client 更改为:

fn handle_client(stream: TcpStream)

并通过以下方式引用它:

Server::handle_client(stream);

但是,我无法从服务器的初始化方法中引用 InternodeServer 的静态方法。编译时,出现如下错误:

test.rs:16:25: 16:46 error: type annotations required: cannot resolve `_ : Server` [E0283]
test.rs:16                         Server::handle_client(stream);
                                   ^~~~~~~~~~~~~~~~~~~~~
test.rs:16:25: 16:46 note: required by `Server::handle_client`
test.rs:16                         Server::handle_client(stream);

有什么办法解决这个问题吗?

最佳答案

下面是错误的较小再现:

use std::thread::Thread;

trait Server {
    fn initialize(&self) {
        Thread::spawn(move || self.handle_client());
    }

    fn handle_client(&self);
}

fn main() {}

问题是传递给 Thread::spawn 的参数必须是 Send .您正在尝试将 self 移动到闭包中,但您的特征不能保证 Send,因此闭包不能是 Send

我们可以尝试使用 trait Server: Send 沿着这条路走下去,但是我们会得到“无法推断适当的生命周期”错误,因为 Send 也需要 '静态 ( for now )。此外,让自己进入闭包似乎很奇怪。

真的,我想你想拆分你的代码。将 handle_client 移动到一个单独的特征中,然后确保该特征的实现是 Send:

use std::thread::Thread;

trait Server {
    fn initialize<D>(&self, driver: D)
        where D: Driver + Send
    {
        Thread::spawn(move || driver.handle_client());
    }
}

trait Driver {
    fn handle_client(&self);
}

fn main() {}

关于multithreading - 在线程中使用特征方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28523778/

相关文章:

java - 如何复用单例模式?

python - 使用 Python 包装的 C++ 类进行并行计算 : performing operations in every element of a vector

python - python 中的多线程和异步套接字

C++:我应该使用全局变量还是类成员指针在模块之间进行通信?

rust - 如何将 impl Fn 存储在枚举类型中?

rust - Tokio 的简单 TCP 回显服务器示例(在 GitHub 和 API 引用上)有什么好的详细解释?

rust - 由于需求冲突,将结构转换为具有生命周期的特征得到 "cannot infer an appropriate lifetime for lifetime parameter ` 'a`”

multithreading - JDBC:我可以在多线程应用程序中共享连接并享受良好的交易吗?

multithreading - timed_mutex 不会在 Cygwin 4.8.2 ('timed_mutex' 下编译,命名空间 'std' 没有命名类型)

design-patterns - 什么时候设计模式会让你的软件变得更糟?