boost::io_service の解釈

坏嘻嘻
坏嘻嘻オリジナル
2018-09-14 09:32:172014ブラウズ

io_servie はタスク キューを実装します。タスクは void(void) 関数です。 Io_servie の最も一般的に使用される 2 つのインターフェイスは post と run です。Post はタスクをタスク キューに配信し、Run はすべての実行が完了するまでキュー内のタスクを実行します。run は N 個のスレッドによって呼び出すことができます。 Io_service は完全にスレッドセーフなキューです。

boost::io_service の解釈

asio は、boost によって提供される C 非同期プログラミング モデル ライブラリであり、そのコア クラス io_service は、主にソケットで使用される、マルチスレッド プログラミングでのタスク キューとタスク分散機能を提供します。 io プログラミングのイベント ドライバーとして (完了ポート、選択、ポーリング、epoll など)。

キュー モデル

各 io_service にはパブリック タスク キューと複数のプライベート タスク キューがあり、パブリック キューは各スレッドで共有され、プライベート キューは各スレッドに排他的です。

boost::io_service の解釈

io_service のタスク実行プロセスは大まかに次のとおりです。

  1. run メソッドを呼び出し、メイン ループに入ります。

  2. # パブリックキューが空かどうかを確認し、空でない場合はタスクを取り出して実行します。タスクの数が 1 より大きい場合は、他のアイドルスレッドも同時に起こします。時間;

  3. タスクの実行が完了し、各スレッドのプライベート キュー内のタスクがパブリック タスク キューに移動されます。イベントが発生すると、リアクターがトリガーされます。これは通常、Linux では epoll であり、対応するイベントのタスクがキューに入れられます。

  4. キューが空の場合、現在のスレッドをアイドル スレッド キューに追加し、待機状態に入り、他のスレッドが起動するのを待ちます (task_operation)。

  5. ユーザーが post を呼び出すと、タスクはパブリック キュー op_queue に直接配信されます。

  6. スレッド プール モデル

    一般的に使用されるスレッド プール モデルは 2 つあります。
1 つは、複数のスレッドがタスク キューを共有し、ユーザーがタスクがタスク キューにポストされると、他のスレッドがキューからタスクの実行を取得するために競合します。 boost::thread と組み合わせると、複数のスレッドで run メソッドを呼び出すことでスレッド プールを実現できます。

using namespace boost;
using namespace boost::asio;
io_service ios;
int thread_num = 10;
thread *t[thread_num] = {0};
// 创建线程池
for(int i = 0; i < thread_num; ++i)
{
    t[i] = new thread(bind(&io_service::run, &ios));
}

// 向任务队列中投递任务,该任务将随机由一个调用run方法的线程执行
ios.post(func);

// 等待线程退出
for(int i = 0; i < thread_num; ++i)
{
    t[i]->join();
}

この種のスレッド プールのボトルネックはタスク キューであり、複数のスレッドであることは簡単にわかります。スレッドがアクセスをめぐって競合するため、大規模な同時プログラムではパフォーマンスが低下しやすくなります。

もう 1 つは、各スレッドがタスク キューを維持することです。ユーザーは、タスク キューの 1 つにタスクをランダムに配信するか、順番に配信するかを選択できます。タスク キュー内のタスクは、そのスレッドでのみ消費されます。にある。この種のスレッド プールには、ブーストの例にも対応する実装 (io_service_pool) があります。基本的な方法は、それぞれがスレッドに対応する複数の io_service オブジェクトを作成することです。コードは次のとおりです。

Windows では一部のクラスの定義が異なるため、以下は Linux 環境に基づいたクラス図です。

#io_service はメイン インターフェイスを定義し、Linux での実装は task_io_service です。

task_io_service は主に 3 つのことを定義します。

boost::io_service の解釈リアクター、リアクターは完了ポート、選択、ポーリング、epoll などのイベント ドライバーです。

パブリック タスク キュー op_queue は、ユーザーによって投稿されたタスクと、reactor によって返されたタスクを格納するために使用されます。 io_service 自体はスレッドを作成しませんが、スレッドのプライベート キューなどの一部のスレッド呼び出し情報を保存します。

  1. さらに、task_io_service はアイドル スレッドのリストも維持し、追加のタスクが到着したときにアイドル スレッドの 1 つを起動します。一般的な Linux のシングル タスク キュー スレッド プールでは、スレッドをウェイクアップするために条件変数が使用されます。マルチコア システムでは、pthread_cond_signal 呼び出しによって待機状態の 1 つ以上のスレッドがウェイクアップされます (https://linux を参照)。 .die.net/man/3/pthread_cond_signal)、タスクは 1 つしかありませんが、アイドル スレッド方式を使用すると、タスクがあるときにアイドル スレッドが 1 つだけ起動されるため、多くの不要な起動を減らすことができます。

  2. thread_info_base クラスは、メモリを 1 つだけ持つ単純なメモリ プールを維持し、メモリ解放を継続的に適用する場合にのみメモリ割り当てのオーバーヘッドを削減できます。
  3. io_service::work の役割: io_service::run は、タスクが完了するとすぐに戻ります。これは、常駐サービス プログラムを作成するときに必要なものではありません。boost が提供する解決策は、work を定義することです。一見すると io_server とは関係のないように見えるこの変数が、実際には run の動作を制御していることがわかります。 作業の実装は驚くほど単純です。コンストラクター内のio_serviceのworked_started()メソッドを使用して、保留中のタスクの数(outstanding_work_)が0より大きいようにします。この場合、io_service::runは処理すべきタスクが常に存在するとみなして戻りません。

  4. 関連する推奨事項:
  5. サービスのステータスに基づく Angular 更新ディレクティブ_AngularJS

AngularJS_AngularJSでのファクトリとサービスの使い方の紹介

#

以上がboost::io_service の解釈の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。