ファイヤープロジェクト
スレッド属性
2007-02-12T15:50+09:00   matsu
スレッド属性について調べてみた.
pthread_attr_initのmanpageによると,スレッドには属性があって,それによってスレッドの挙動が変わるらしい. スレッドの属性には,
  • デタッチ状態
  • スケジューリングポリシー
  • スケジューリングパラメータ
  • スケジューリングの継承
  • スコープ
があるらしい.
スレッドにスレッド属性を設定するには,まずスレッド属性オブジェクトを作成,初期化する必要がある. スレッド属性の初期化は以下で行う.
int pthread_attr_init(pthread_attr_t *attr);
pthread_attr_initによって,各スレッド属性はデフォルト値に設定される. attrには,スレッド属性へのポインタを設定する. pthread_attr_initは成功すれば0,失敗すれば0以外を返す. スレッド属性オブジェクトを初期化したら,あとは任意の属性を任意に設定,取得する. スレッド属性の設定には以下を使用する.
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit);
int pthread_attr_setscope(pthread_attr_t *attr, int scope);
それぞれattrで指定したスレッド属性オブジェクトに,第二引数で指定した値を設定する. 設定値はpthread_attr_initに記述されている定数を指定する. 設定値が不正だとエラーが返る. スレッド属性の取得には以下を使用する.
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int  *pol-icy);
int pthread_attr_getschedparam(const  pthread_attr_t *attr, struct sched_param *param);
int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit);
int pthread_attr_getscope(const pthread_attr_t *attr, int *scope);
それぞれattrにて指定したスレッド属性から属性値を取り出し,第二引数で指定した領域に設定する. 初期化したスレッド属性オブジェクトは,スレッド生成の際に指定することで,生成されたスレッドに適用される.
では設定効果がわかりやすい,デタッチ状態の設定を試してみる.
このサンプルでは,二つのスレッドthread_a,thread_bを生成している. 生成に先だって,それぞれスレッド属性を初期化設定している. thread_aでは,デタッチ状態を合流可能(PTHREAD_CREATE_JOINABLE)に設定している(※).
pthread_attr_t attr_a;
// スレッドaの属性初期化
status = pthread_attr_init(&attr_a);
if (status != 0)
  {
    MY_ABORT("failed to attr_init thread_a");
  }
// スレッドa属性を合流可能に設定
status = pthread_attr_setdetachstate(&attr_a,
                                     PTHREAD_CREATE_JOINABLE);
if (status != 0)
  {
    MY_ABORT("failed to attr_setdetachstate thread_a");
  }
thread_bでは,デタッチ状態をデタッチ(PTHREAD_CREATE_DETACHED)に設定している.
pthread_attr_t attr_b;
// スレッドbの属性初期化
status = pthread_attr_init(&attr_b);
if (status != 0)
  {
    MY_ABORT("failed to attr_init thread_b");
  }

// スレッドb属性をデタッチ済に設定
status = pthread_attr_setdetachstate(&attr_b,
                                     PTHREAD_CREATE_DETACHED);
if (status != 0)
  {
    MY_ABORT("failed to attr_setdetachstate thread_b");
  }
属性オブジェクトを設定したら,あとはスレッド生成の際にそれを指定する.
// スレッドaを生成
status = pthread_create (&thread_a, &attr_a, myThread, &thread_a_arg);
if (status != 0)
  {
    MY_ABORT("failed to create thread_a");
  }
...省略...
// スレッドbを生成
status = pthread_create (&thread_b, &attr_b, myThread, &thread_b_arg);
if (status != 0)
  {
    MY_ABORT("failed to create thread_b");
  }
以上の処理で,メインスレッドは前頁と同じ挙動を示すようになる. つまり,合流可能なthread_aへのjoin処理は成功し,デタッチ済のthread_bへのjoin処理は失敗する. 以下に実行結果を示す.
$ ./thread_attr 
ababaaba
expected result
※ 合流可能はデフォルト値なので,設定しなくてもよいのだが,ここでは試しにやってみている.
matsu(C)
Since 2002
Mail to matsu