/*** * この時点で子スレッドは存在しないものと仮定する. * 通常のアプリであれば numは128くらいあれば十分であろう. * この値の指定に上限はない(単にListのメモリサイズに影響するのみで * 大きな値を指定してもたかが知れている). * 実際に使用する数よりもやや多めに指定した方がよい. * ぎりぎりくらいに設定するとissue処理の際、探索に時間が * かかる可能性が高くなってしまう. */ void ZnkThreadList_initiate( size_t num ) { ZnkBfr thlist; ZnkMutex* mtxp = znThreadList_theMutex(); if( *mtxp == NULL ){ *mtxp = ZnkMutex_create(); } thlist = znThreadList_theList(); ZnkBfr_resize( thlist, num * sizeof( struct znThreadListElem ) ); allocInternal( thlist, 0, num ); }
/*** * この関数は、lockは掛かっている状態で呼ばれることを前提とする. */ static ZnkThreadInfo issueInfoInteranal( size_t* thno ) { static size_t begin = 0; ZnkBfr thlist = znThreadList_theList(); const size_t num = znThreadList_getListNum( thlist ); struct znThreadListElem* elemp = NULL; size_t idx; struct znThreadListElem* data = (struct znThreadListElem*)ZnkBfr_data( thlist ); /*** * beginの位置はサイクリックに移動させる. */ if( begin >= num ){ begin = num; } for( idx=begin; idx<num; ++idx ){ elemp = data + idx; if( !elemp->used_ ){ /* 現在未使用 */ begin = idx; /* 次回検索を高速化するためのヒューリスティック */ *thno = idx; elemp->used_ = true; /* 使用中に切り替える */ return elemp->info_; } } for( idx=0; idx<begin; ++idx ){ elemp = data + idx; if( !elemp->used_ ){ /* 現在未使用 */ begin = idx; /* 次回検索を高速化するためのヒューリスティック */ *thno = idx; elemp->used_ = true; /* 使用中に切り替える */ return elemp->info_; } } /*** * 用意していたThreadの定員数がオーバーした. * この状態はかなりイレギュラーである. * 本来ならばこのような状況が発生しないようにinit時に与えるnumを十分に用意すべきである. * ここでは、num をそれまでの 2 倍に増やす. */ ZnkBfr_resize( thlist, 2 * num * sizeof(struct znThreadListElem) ); allocInternal( thlist, num, num ); data = (struct znThreadListElem*)ZnkBfr_data( thlist ); *thno = num; elemp = data + num; elemp->used_ = true; /* 使用中に切り替える */ return elemp->info_; }
ExecutablePool::Allocation alloc(size_t size) { return ExecutablePool::Allocation(allocInternal(size), size); }