Sun Studio 12: C++ ユーザーズガイド

11.4.8 アプリケーションの例

ここでは、libC ライブラリの iostream オブジェクトを安全な方法で使用するマルチスレッドアプリケーションの例を示します。

このアプリケーションは、最大で 255 のスレッドを生成します。それぞれのスレッドは、別々の入力ファイルを 1 行ずつ読み込み、標準出力ストリーム cout を介して共通の出力ファイルに書き出します。この出力ファイルは、すべてのスレッドから共有されるため、出力操作がどのスレッドから行われたかを示す値をタグとして付けます。


例 11–13 iostream オブジェクトをマルチスレッドで使用しても安全な方法で使用


// タグ付きスレッドデータの生成
// 出力ファイルに次の形式で文字列を書き出す
//         <タグ><データ文字列>\n
// ここで、<タグ> は unsigned char 型の整数値
// このアプリケーションで最大 255 のスレッドを実行可能
// <データ文字列> は任意のプリント可能文字列
// <タグ> は 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;
}

int 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;

// thread_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;
}