20章非同期プログラミング

チャットサーバを書くことを考えてみよう。複数のネットワーク接続に対して、入ってくるパケットの解析、返すパケットの構築、セキュリティパラメータの管理、チャットグループ登録の処理などを行う必要がある。このような処理を多数のネットワーク接続に対して同時に行うには、何らかの構造化が必要となる。

個々のネットワーク接続に対して個別にスレッドを割り当てられれば理想的だ。

use std::{net, thread};

let listener = net::TcpListener::bind(address)?;

for socket_result in listener.incoming() {
    let socket = socket_result?;
    let groups = chat_group_table.clone();
    thread::spawn(|| {
        log_error(serve(socket, groups));
    });
}

このコードは、新しく接続が来るごとに新しいスレッドを起動して、そのスレッドでserve関数を実行する。serve関数は1つの接続の管理にだけ集中することができる。

この方法はうまくいくが、想定していたよりもこのチャットサーバの人気が出て、突然ユーザ数が数万人になってしまうと破綻する。1つのスレッドのスタックは100KiB†1を超えることも珍しくない。すると、スレッドのスタックがサーバのメモリを数GiB使用することになってしまうが、これは望ましいことではないだろう。複数のプロセッサに仕事を分散するためにはスレッドが必要で有用だが、スレッドのメモリ消費量は大きすぎる。このような場合のために、スレッドを補完する仕事の分割手法が必要になる。 ...

Get プログラミングRust 第2版 now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.