6

私はDを初めて使用し、練習用の単純なマルチスレッドサーバーを作成しています。Cでクライアントハンドラスレッドを開始するための一般的なパラダイムは、新しく受け入れられたソケットのファイル記述子をpthread_create()に渡すことですが、Dのstd.concurrency.spawn()は、ソケットが変更可能であるため、ソケットを渡すことを許可しません。 2つのスレッドでアクセスできます。

もちろん、私は実際には不変のソケットを望んでいません(そのため、必要がない限り、メインスレッドにキャストしたくないのです)-可変のソケットを渡してスコープ外にしたいメインスレッドで。どうすればいいですか?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) {
    ...
}

エラー:staticassert「可変スレッドローカルデータへのエイリアスは許可されていません。」...ここからインスタンス化:スポーン!(ソケット)

4

2 に答える 2

7

ソケットを共有にキャストし、clienthandlerに再度戻す必要があります

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

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

この理由は、指定されていない限り、すべてのローカル変数は暗黙的にスレッドローカルsharedであり、共有または不変への参照のみが引数としてspawn(またはsend)に渡され、値によって渡されるもの(参照とプリミティブのない構造体)は問題ないためです。

また、現在の実装では、新しく生成されたスレッドが実行される前にソケットが閉じられる可能性があるため、ハンドラーにcloseintを配置する必要があります。

于 2013-01-18T11:16:18.330 に答える
1

ここでの問題は、ローカル変数であるソケットではありません。これはclientHandlerであり、その宣言は表示されていませんが、受け入れられたソケットごとに新しい宣言があるはずの場合、エラーメッセージに示されているように、明らかにスレッドローカルです。ヒントは、&演算子を指す「エイリアス」という単語です。

于 2013-01-18T08:49:00.557 に答える