mytt.c

最終更新:2009/10/18

mytt.c

001: /* mytt.c
002:  * スレッドテーブルのサンプル
003:  * ・保持するスレッド数の上限を設定。
004:  */
005: 
006: #include "apr_general.h"
007: #include "apr_errno.h"
008: #include "apr_thread_proc.h"
009: 
010: #include "mytt.h"
011: 
012: /*
013:  * スレッドテーブル
014:  * ・スレッドテーブルは処理中のサブスレッドのスレッドハンドルを保持する配列。
015:  * ・インデクス変数で次の位置をポイントする。
016:  * 条件:
017:  * ・スレッドテーブルはメインスレッドでのみ操作する。
018:  * ・スレッドテーブルはサブスレッドから操作してはならない。
019:  * ルール:
020:  * (1)arr[i]==NULL の時、arr[i] はサブスレッドを保持していない。
021:  *   また、過去にサブスレッドを保持していた場合は同期済である。
022:  * (2)arr[i]!=NULL の時、arr[i] は同期前のサブスレッドを保持している。
023:  */
024: 
025: 
026: /* 【必須】スレッドテーブルの初期化
027:  * ・必ずメインスレッドの最初に呼ぶこと。
028:  */
029: 
030: void my_thread_table_init(
031:   my_thread_table *mtt /* IN/OUT: スレッドテーブル(呼び出し元で領域確保する) */
032:   ,int num     /* IN:スレッドテーブルのサイズ */
033:   , apr_pool_t *pool   /* OUT:メモリプール */
034: ) {
035: 
036:   if (!mtt) {
037:     return;
038:   }
039:   if (num<1) {
040:     return;
041:   }
042: 
043:   mtt->num = num;
044:   mtt->pool = pool;
045:   mtt->index = 0;
046:   mtt->arr
047:     = (apr_thread_t**)apr_palloc(mtt->pool, sizeof(apr_thread_t*) * mtt->num);
048:   memset(mtt->arr, 0, sizeof(apr_thread_t*) * mtt->num);
049:   apr_threadattr_create(& mtt->attr, mtt->pool); /* デフォルトのスレッド属性の生成 */
050: }
051: 
052: 
053: /* スレッドの生成
054:  * 返り値:
055:  *   成功時には APR_SUCCESS。
056:  */
057: 
058: apr_status_t my_thread_create (
059:   my_thread_table *mtt       /* IN:スレッドテーブル */
060:   , apr_thread_t **thd       /* OUT:生成したサブスレッドのスレッドハンドル */
061:   , apr_thread_start_t func  /* IN:サブスレッドが処理する関数 */
062:   , void *data               /* IN:サブスレッドが処理する関数で使うデータ */
063: ) {
064:   apr_status_t rv = APR_SUCCESS;
065:   char error_buf[32];
066: 
067:   /* スレッドテーブルのインデクス変数は次の位置を指している。 */
068: 
069:   /* スレッドテーブルの次の位置がヌルでない=サブスレッドは未同期(ルール(2)) */
070:   
071:   if (mtt->arr[mtt->index]) {
072: 
073:     /* サブスレッドの同期 */
074:     rv = apr_thread_join(&rv, mtt->arr[mtt->index]);
075: 
076:     if (rv != APR_SUCCESS) { /* 同期に失敗… */
077:     
078:       if(1)printf("ERROR: apr_thread_join: %s\n",
079:          apr_strerror(rv, error_buf, sizeof(error_buf)));
080: 
081:       /* スレッドテーブルのインデックス変数を次の位置に。
082:        * 理由:このエラーで呼び出し元が処理を終わらせてくれればよいが、
083:        * また呼ばれた時に同じarr[index]に対してapr_thread_joinする。
084:        * もしこのarr[index]が指すスレッドの異常が原因でエラーが発生
085:        * していたとすると、再度同じエラーが発生する可能性があるので、次の
086:        * 位置に変更しておく。
087:        * ただし、この対処は問題を先送りしてるだけかもしれない。
088:        */
089:       mtt->index = (mtt->index+1) % mtt->num;
090: 
091:       return rv;
092:     }
093: 
094:     /* 同期したサブスレッドのスレッドテーブル中のレコードをヌルに(ルール(1)) */
095:     mtt->arr[mtt->index] = NULL;
096:   }
097:   
098:   /* APR でスレッド生成 */
099:   rv = apr_thread_create(& mtt->arr[mtt->index], mtt->attr, func, data, mtt->pool);
100:   
101:   if (rv == APR_SUCCESS) {
102:     *thd = mtt->arr[mtt->index];
103:     
104:     /* スレッドテーブルのインデックス変数を次の位置に */
105:     
106:     mtt->index = (mtt->index+1) % mtt->num;
107:   }
108: 
109:   if (rv != APR_SUCCESS) {
110:     if(1)printf("%s\n", apr_strerror(rv, error_buf, sizeof(error_buf)));
111:   }
112: 
113:   return rv;
114: }
115: 
116: /* 【必須】スレッドテーブルのリセット
117:  * ・スレッドテーブルが保持する全サブスレッドの同期をしてからスレッドテーブルをリセットする。
118:  * ・メインスレッドで最後に必ず呼ぶこと。
119:  * 返り値:
120:  *   成功時には APR_SUCCESS。
121:  */
122: 
123: apr_status_t my_thread_table_clear (
124:   my_thread_table *mtt /* IN:スレッドテーブル */
125: ) {
126:   apr_status_t rv = APR_SUCCESS;
127:   int i=0;
128: 
129:   if (!mtt) {
130:     return APR_SUCCESS;
131:   }
132: 
133:   for (i=0; i<mtt->num; i++) {
134:     if (mtt->arr[i]) {
135:       rv = apr_thread_join(&rv, mtt->arr[i]);
136:       if (rv != APR_SUCCESS) {
137:          char error_buf[32];
138:          if(1) fprintf(stderr,
139:             "ERRPR: apr_thread_join: %s\n",apr_strerror(rv, error_buf, sizeof(error_buf)));
140: 
141:          /* return rv; */
142:          
143:          /* ループを抜けたいところだが、残りのサブスレッドの
144:           * 同期が気になるのでループを継続する。
145:           */
146:       }
147:       mtt->arr[i] = NULL;
148:     }
149:   }
150:   
151:   /* スレッドテーブルをリセット */
152:   mtt->arr = NULL;
153:   mtt->num = 0;
154:   mtt->index = 0;
155:   mtt->attr = NULL;
156:   mtt->pool = NULL;
157:   
158:   return rv;
159: }
Copyright (C) KAKU PROJECT (2009)KAKU PROJECT (2009)