2013-01-18 28 views
5

私はDが新しく、実践のためには単純なマルチスレッドサーバーを作成しています。 Cでクライアントハンドラスレッドを開始するための一般的なパラダイムは、新しくaccept()されたソケットのファイル記述子をpthread_create()に渡すことですが、Dのstd.concurrency.spawn()はSocketを渡すことはできません。 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) { 
    ... 
} 

生成します。エラー:静的アサート「変更可能なスレッドローカルデータへのエイリアスが許可されていません。」 ...ここからインスタンス化されました:スポーン!(ソケット)

答えて

6

あなたはClientHandlerの中で再び共有にソケットをキャストし、する必要が

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

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

この理由は、すべてのローカル変数が暗黙のうちに共有または不変缶への参照のみをsharedを指定しない限り、ローカルスレッド、およびされていることです値渡しのもの(参照とプリミティブのない構造体)は、

(またはsend)の引数として渡すこともできます。現在の実装と同様に、ハンドラをclose intにする必要があります。ニューールy生成されたスレッドは実行する機会があります

+0

完璧に作業し、追加情報をありがとう!これは、このようなことをする慣用的な方法ですか、それとももっと良い方法がありますか? Dのキャスティングは、私が間違ったことをしているように(つまりCとは反対に)、まったく同じように感じます。 – Dan

+0

@Dan last最後に私は(共有された) 'shared'のセマンティクスを明確に定義していませんでしたが、それ以後変更されたかどうかはわかりません。 –

+1

何も変更されていません。しかし、Dコミュニティ全体は、「共有」が明確になるのを待っています。 – DejanLekic

1

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

+0

申し訳ありませんが、私は 'clientHandler()'の宣言を追加して質問を明確にしました。これはグローバルスコープで宣言された関数なので、おそらく私が思っていたよりも混乱しているかもしれませんが、それは問題のスレッドローカルデータではないのでしょうか。 – Dan

+0

@ダン・オク、何ですか?スコープ()がそれに何らかの影響を与えない限り、ソケットではありません。私は専門家ではありません。 – EJP

+0

'scope(exit)'は、スコープの最後に 's.close()'が呼び出されることを保証します。これは、Javaの 'finally'キーワードと同じです。確かに、それを追加したところでは意味がありませんが、それを削除するか、別の場所に配置することは、コンパイルエラーには影響しません。私は[グローバル変数](http://dlang.org/migrate-to-shared.html)がスレッドローカルに自動的に変換されることを読んだが、これは関数には適用すべきではなく、関数の別名を(ローカル、私は思う)ラムダ式でも同じエラーが発生します。 – Dan

関連する問題