6

我是 D 新手,我正在编写一个简单的多线程服务器进行练习。在 C 中启动客户端处理程序线程的一个常见范例是将新接受 () 的套接字的文件描述符传递给 pthread_create(),但 D 的 std.concurrency.spawn() 不允许我传递套接字,因为它是可变的并由两个线程访问。

当然,我实际上并不想要一个不可变的套接字(这就是为什么我真的不想在主线程中强制转换它,除非我必须这样做) - 我想传递一个可变的套接字并让它超出范围在主线程中。我该怎么办?应该(/可以)我tid.send(s)用来让线程使用套接字吗?出于某种原因,这对我来说似乎很笨拙。

我现在的代码:

void main() {
    Socket listener = new TcpSocket;
    ...
    for (;;) {
        Socket s = listener.accept();
        scope(exit) s.close();

        auto tid = spawn(&clientHandler, s);
    }
}

void clientHandler(Socket s) {
    ...
}

这会产生:错误:静态断言“不允许使用可变线程本地数据的别名。” ...从这里实例化:spawn!(Socket)

4

2 回答 2

7

您需要在客户端处理程序中将套接字转换为共享并再次返回

auto tid = spawn(&clientHandler, cast(shared) s);

void clientHandler(shared Socket s) {
    Socket sock = cast(Socket)s;
    scope(exit)sock.close();
}

这样做的原因是,除非指定shared,否则所有局部变量都是隐式线程局部的,并且只有对共享或不可变的引用才能作为参数传递给spawn(或send),而按值传递的东西(没有引用和原语的结构)很好

您还应该将 close int 处理程序与您当前的实现一样,套接字可能会在新生成的线程有机会运行之前关闭

于 2013-01-18T11:16:18.330 回答
1

这里的问题不在于套接字,它是一个局部变量。它是clientHandler,您没有显示它的声明,但显然它是线程本地的,正如它在错误消息中所说的那样,当每个接受的套接字应该有一个新的套接字时。提示是“别名”这个词,它指的是 & 运算符。

于 2013-01-18T08:49:00.557 回答