C++ ライブラリ・リファレンス

アプリケーションの例

次の例では、複数のスレッドを使用するアプリケーションの例を示します。この例では、libC ライブラリの iostream オブジェクトを「MT-安全」で使用します。

このアプリケーションでは、スレッドを 255 個まで作成します。各スレッドはそれぞれ異なる入力ファイルから一度に 1 行ずつデータを読み込み、そのデータを出力ファイルに書き込みます。そのとき標準出力ストリーム cout を使用します。出力ファイルは全スレッドで共有するため、どのスレッドから出力されたかを示すタグを付けます。


例 4-13 iostream オブジェクトを「MT-安全」で使用

// <ストリングデータ> は、任意の印刷可能文字
// タグは、整数値を char 型として書き込むため、
// 出力ファイルを表示するときは、次のように od を使用する必要がある
//           od -c out.file |more

#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>
#include <fstream.h>
#include <thread.h>

struct thread_args {
  char* filename;
  int thread_tag;
};

const int thread_bufsize = 256;

// 各スレッドのエントリルーチン
void* ThreadDuties(void* v) {
// 現スレッドの引数の取得
  thread_args* tt = (thread_args*)v;
  char ibuf[thread_bufsize];
  // スレッドの入力ファイルをオープン
  ifstream instr(tt->filename);
  stream_locker lockout(cout, stream_locker::lock_defer);
  while(1) {
  // 一度に 1 行を読み込み
    instr.getline(ibuf, thread_bufsize - 1, '¥n');
    if(instr.eof())
      break;

// 入出力操作を不可分命令的に実行するため、cout ストリームをロック
    lockout.lock(); 
  // データにタグを付けて cout に出力
    cout << (unsigned char)tt->thread_tag << ibuf << "¥n";
    lockout.unlock();
  }
  return 0;
}

main(int argc, char** argv) {
  // argv: 1+ 各スレッドのファイル名リスト
   if(argc < 2) {
     cout << "usage: " << argv[0] << " <files..>¥n";
     exit(1);
   }
  int num_threads = argc - 1;
  int total_tags = 0;

// スレッド ID の配列
  thread_t created_threads[thread_bufsize];
// スレッドのエントリルーチンへの引数の配列
  thread_args thr_args[thread_bufsize];
  int i;
  for( i = 0; i < num_threads; i++) {
    thr_args[i].filename = argv[1 + i];
// スレッドへのタグの割り当て − タグの値は 255 以下
    thr_args[i].thread_tag = total_tags++;

// スレッドの生成
    thr_create(0, 0, ThreadDuties, &thr_args[i], 
	       THR_SUSPENDED, &created_threads[i]);
  }

  for(i = 0; i < num_threads; i++) {
    thr_continue(created_threads[i]);
  }
  for(i = 0; i < num_threads; i++) {
    thr_join(created_threads[i], 0, 0);
  }
  return 0;
}