mytt.c
最終更新:2009/10/18
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: }
KAKU PROJECT (2009) |