FreeBASIC CondWait
目次→実行時ライブラリー参考→多重スレッド化サポート→CONDWAIT←オリジナル・サイト
何らかの条件が満たされるまで、現在のスレッドの実行を、止めます。
構文:
用法:
Condwait ( handle, mutex )
パラメタ:
handle
条件変数のハンドル。
mutex
この条件変数に関連しているミューテックス。条件変数は、条件をテストして、Condwait を呼ぶとき、ロックされなければなりません。
記述:
Condwait を呼び出すとき、
mutex を、先にロックしておかなければなりません。(
Condsignal か
Condbroadcast で使われるものと同じ
mutex を使用)。
mutex のアトミック・ロック解除と、条件変数の待機が、発生します。
アトミックとは、原子で、これ以上分けられないことから、不可分操作をいいます。
一連の処理が不可分の一体として成功・失敗いずれかになり、かつ処理途中の状態にほかからアクセスできない状態。
呼び出しスレッドの実行は中断され、条件変数が通知されるまで、CPU 時間を消費しません。
条件変数が通知されると、
mutex は再びロックされ、
Condwait 呼び出しの後、呼び出し元が所有する
mutex を使って、実行がスレッドに戻ります。
呼び出し側は、
Condwait サブルーチンを完了して、
Condwait 呼び出し後の実行を再開できるように、
mutex のロックを解除する、責任があります。
注: 結果として起こる誤った起床を防ぐために、保護された方法で
Condwait を使用するのは良い習慣です。
このため、スレッドが待機を終了したときに、ブール述語が実際に真(
Condsignal か
Condbroadcast を実行する直前に、別のスレッドによって、述語が true に設定されます)であることをチェックするループ内に、
Condwait が配置されます:
signal-caller:
predicate = true
Condsignal(handle)
waiting-called:
While predicate <> true
Condwait(handle, mutex)
Wend
predicate = false
ループは、述部が真である場合にだけ、終了できます。
一方、スレッドがループに到達する前に、述語がすでに真である場合、
Condwait は完全にスキップされます
(そうでなければ失われるはずの、
Condsignal や
Condbroadcast のケースを考慮に入れることができます。これは、最初のスレッドが実際にこれを待機する前に、2番目のスレッドで早まって実行されるためです。)
詳細なコーディングについては、下記の例を参照ください。
例:
' この簡単なコード例は、いくつかの条件変数ルーチンの使用方法を示します。
' メインルーチンは、3つのスレッドを作成します。
' スレッドの二つは、"count" 変数を更新します。
' 第三のスレッドは、"count" 変数が指定された値に達するまで、待機します。
#define numThread 3
#define countThreshold 6
Dim Shared As Integer count = 0
Dim Shared As Any Ptr countMutex
Dim Shared As Any Ptr countThresholdCV
Dim As Any Ptr threadID(0 To numThread-1)
Dim Shared As Integer ok = 0
Sub threadCount (ByVal p As Any Ptr)
Print "開始 threadCount(): thread#" & p
Do
Print "threadCount(): thread#" & p & ", ロック mutex"
MutexLock(countMutex)
count += 1
' count の値と、条件に達したときの待ちスレッドの信号を、チェック。
' mutex がロックされている間、これが起こることに注意してください。
If count >= countThreshold Then
If count = countThreshold Then
Print "threadCount(): thread#" & p & ", count = " & count & ", しきい値に達し、開錠 mutex"
ok = 1
CondSignal(countThresholdCV)
Else
Print "threadCount(): thread#" & p & ", count = " & count & ", しきい値を超え、開錠 mutex"
End If
MutexUnlock(countMutex)
Exit Do
End If
Print "threadCount(): thread#" & p & ", count = " & count & ", 開錠 mutex"
MutexUnlock(countMutex)
Sleep 100, 1
Loop
End Sub
Sub threadWatch (ByVal p As Any Ptr)
Print "開始 threadWatch(): thread#" & p & ", ロック mutex, 条件待ち"
MutexLock(countMutex)
' Condwait ルーチンは、それが待っている間、自動的、原子的に、mutex を開錠することに注意して下さい。
While ok = 0
CondWait(countThresholdCV, countMutex)
Wend
Print "threadWatch(): thread#" & p & ", 条件信号を受信"
Print "threadWatch(): thread#" & p & ", count now = " & count & ", 開錠 mutex"
MutexUnlock(countMutex)
End Sub
' mutex と条件変数を作成します。
countMutex = MutexCreate
countThresholdCV = CondCreate
' スレッドを生成
threadID(0) = ThreadCreate(@threadWatch, Cast(Any Ptr, 1))
threadID(1) = ThreadCreate(@threadCount, Cast(Any Ptr, 2))
threadID(2) = ThreadCreate(@threadCount, Cast(Any Ptr, 3))
' すべてのスレッドが完了するまで待つ
For I As Integer = 0 To numThread-1
ThreadWait(threadID(I))
Print "Main(): 待ち状態 thread#" & I+1 & " 実行"
Next I
MutexDestroy(countMutex)
CondDestroy(countThresholdCV)
Sleep
プラットホーム差:
- Condwait は、FreeBASIC の DOS バージョンと、DOS 目標では、利用できません。多重スレッド化は、DOS カーネルによっても、拡張を使っても、サポートされないからです。
- Linux では、スレッドは、常に作成された順に、開始されます。Win32 では、これを想定できません。
これは OS の問題で、FreeBASIC の問題ではありません。
方言差:
QBからの違い:
参照:
ページ歴史:2023-03-09 13:04:22
日本語翻訳:WATANABE Makoto、原文著作者:AntoniGual