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) |