いつもお世話になっております。すうと申します。
訳ありでCMutexをラップしたSemaphoreクラス(紛らわしくてすみません・・)
を作成して使用しているのですが問題がございます。
一方のスレッドがSemaphore::take()でロックした状態で、もう一方のスレッド
がtake()するとIsLocked()でブロックされてしまいます。ということで、タイムアウト
付きのtake()を作成したいのですが、時間をカウントできません。
ヘルプではIsLocked()はオブジェクト状態とありますので、すぐにリターンすると理解
したのですが、何か使用方法が不適切なのでしょうか?
動作環境はWin2000SP3、VC++6.0です。
どちら様かご存知の方がいらっしゃいましたら、ご教示お願いいたします。
〇Semaphoreクラスの抜粋です。
Semaphore::Semaphore ( char *name, int option ){
_pMutex = new CMutex( FALSE, name, NULL );
・・・・・
}
CSingleLock *Semaphore::openAccess(){
return new CSingleLock( _pMutex);
}
int Semaphore::give (CSingleLock *pLock){
return ( pLock->Unlock() ) ? OK: ERROR;
}
int Semaphore::take (CSingleLock *pLock){
while( pLock->IsLocked() ){
Sleep(1);
}
return ( pLock->Lock() ) ? OK: ERROR;
}
〇あるワーカースレッドでの使用個所です。
testSemはSemaphoreインスタンスポインタで、スレッド生成時に
引数で渡しています。
CSingleLock *pLock = testSem->openAccess();
while(1){
・・・・・
testSem->take(pLock);
・・・・・
testSem->give(pLock);
・・・・・
}
以上です。宜しくお願いいたします。
> 一方のスレッドがSemaphore::take()でロックした状態で、もう一方のスレッド
> がtake()するとIsLocked()でブロックされてしまいます。
pLock->IsLocked() の呼び出しから帰ってこないと言うことですか?
CSingleLock::IsLocked()のソースを見ると、
_AFXMT_INLINE BOOL CSingleLock::IsLocked()
{ return m_bAcquired; }
となっており、
この関数から戻らないということは考え難いです。
次のようにしてみてはいかがでしょう。
int Semaphore::take (CSingleLock *pLock, DWORD timeout){
return ( pLock->Lock(timeout) ) ? OK: ERROR;
}
dairygoods様、レスありがとうございます。
ご指摘をいただき、再度調べたところ、IsLockedではゼロですぐにリターンして
その後のLock()で戻ってきていないということが判りました(すみません)。
IsLockedではCMutexの状態をCSingleLockオブジェクトを通して返してくれる
と理解していたのですが(ヘルプには関連する同期オブジェクト状態を返すとの
記述)、そうではなくCSingleLockインスタンスの状態を返すだけのようです。
ご教示いただいたtake()の実装を最初行っていたのですが、同一スレッドが連続
してtake()を実行すると(すなわちCSingleLock::Lockを連続で)、ASSERTで
停止してしまうので、その対策としてIsLockedを追加していました。
とりあえず本件は解決として、別の回避策を検討しようと思います。
お手数をおかけいたしました。