FreeBASIC マニュアルのトップに戻る

FreeBASIC CondWait

目次→実行時ライブラリー参考→多重スレッド化サポートCONDWAIT←オリジナル・サイト

CONDWAIT 左にメニュー・フレームが表示されていない場合は、ここをクリックして下さい

←リンク元に戻る プログラム開発関連に戻る

何らかの条件が満たされるまで、現在のスレッドの実行を、止めます。

構文:
declare sub Condwait ( byval handle as any ptr, byval mutex as any ptr )

用法:
Condwait ( handle, mutex )

パラメタ:
handle
条件変数のハンドル。
mutex
この条件変数に関連しているミューテックス。条件変数は、条件をテストして、Condwait を呼ぶとき、ロックされなければなりません。

記述:
この関数は、スレッドが、なにか他のスレッドの Condsignal か、Condbroadcast のハンドルで呼ばれるまで、スレッドを止めます。

条件付きが Condcreate でスレッドが開始すると、そのうちの1つ以上(主プログラムを実行している暗黙の主スレッドを含む)が条件付きで Condwait に設定されます。これらは、他のスレッドが Condsignal して、待機中のスレッドが再起動できることを示すまで、停止します。
Condbroadcast を使うと、条件を待機しているすべてのスレッドを再起動できます。
プログラムの最後に、Conddestroy を使って OS のリソース・リークを回避する必要があります。

Condwait を呼び出すとき、mutex を、先にロックしておかなければなりません。(CondsignalCondbroadcast で使われるものと同じ mutex を使用)。
mutex のアトミック・ロック解除と、条件変数の待機が、発生します。
アトミックとは、原子で、これ以上分けられないことから、不可分操作をいいます。
一連の処理が不可分の一体として成功・失敗いずれかになり、かつ処理途中の状態にほかからアクセスできない状態。

呼び出しスレッドの実行は中断され、条件変数が通知されるまで、CPU 時間を消費しません。
条件変数が通知されると、mutex は再びロックされ、Condwait 呼び出しの後、呼び出し元が所有する mutex を使って、実行がスレッドに戻ります。
呼び出し側は、Condwait サブルーチンを完了して、Condwait 呼び出し後の実行を再開できるように、mutex のロックを解除する、責任があります。

注: 結果として起こる誤った起床を防ぐために、保護された方法で Condwait を使用するのは良い習慣です。
このため、スレッドが待機を終了したときに、ブール述語が実際に真(CondsignalCondbroadcast を実行する直前に、別のスレッドによって、述語が true に設定されます)であることをチェックするループ内に、Condwait が配置されます:
signal-caller:
predicate = true
Condsignal(handle)

waiting-called:
While predicate <> true
Condwait(handle, mutex)
Wend
predicate = false

ループは、述部が真である場合にだけ、終了できます。
一方、スレッドがループに到達する前に、述語がすでに真である場合、Condwait は完全にスキップされます (そうでなければ失われるはずの、CondsignalCondbroadcast のケースを考慮に入れることができます。これは、最初のスレッドが実際にこれを待機する前に、2番目のスレッドで早まって実行されるためです。)

詳細なコーディングについては、下記の例を参照ください。

例:
CondcreateCondsignal も参照下さい。

' この簡単なコード例は、いくつかの条件変数ルーチンの使用方法を示します。
' メインルーチンは、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


プラットホーム差:

方言差:

QBからの違い:

参照:

多重スレッド化サポート に戻る
←リンク元に戻る プログラム開発関連に戻る
ページ歴史:2023-03-09 13:04:22
日本語翻訳:WATANABE Makoto、原文著作者:AntoniGual

ホームページのトップに戻る

表示-非営利-継承