ここでの問題は、優先度そのものではありません。スレッドが保持しているロックを元に戻し、別のスレッドがロックを取得できるようにする必要があるという事実です。「優先度」は、一連の実行可能なスレッドの実行をスケジュールする必要があることに関連します。実行できないスレッドを実行可能にしたい (別のスレッドが保持するロックを待機しているため)。
したがって、実装したい(あなたが言ったように):
if (ThisThreadNeedsToSuspend()) { ReleaseDiskLock(); WaitForResume(); ReacquireDiskLock(); }
あなたは(賢明に)スコープ付きロックを使用しているので、ロジックを逆にしたいと思います:
while (file_is_not_finished) {
WaitUntilThisThreadCanContinue();
CritSecLock diskLock(blah);
process_part_of_the_file();
}
ReleasePriority();
...
void WaitUntilThisThreadCanContinue() {
MutexLock lock(thread_priority_mutex);
while (thread_with_priority != NOTHREAD and thread_with_priority != thisthread) {
condition_variable_wait(thread_priority_condvar);
}
}
void GiveAThreadThePriority(threadid) {
MutexLock lock(thread_priority_mutex);
thread_with_priority = threadid;
condition_variable_broadcast(thread_priority_condvar);
}
void ReleasePriority() {
MutexLock lock(thread_priority_mutex);
if (thread_with_priority == thisthread) {
thread_with_priority = NOTHREAD;
condition_variable_broadcast(thread_priority_condvar);
}
}
条件変数について調べてください。最近のすべての OS には条件変数があり、同様の基本操作があります。Boost と C++11 にもあります。
関数を書くprocess_part_of_the_file
ことができない場合、このように構造化することはできません。代わりに、ディスクロックを解放して回復できるスコープ付きロックが必要です。これを行う最も簡単な方法は、それをミューテックスにすることです。そうすれば、同じミューテックスを使用して condvar を待つことができます。ミューテックス/condvar ペアとthread_with_priority
オブジェクトは、ほぼ同じ方法で引き続き使用できます。
優先度の変更に対するシステムの応答性に応じて、「ファイルの一部」のサイズを選択します。非常に応答性が必要な場合、スキームは実際には機能しません-これは協調マルチタスクです.
私はこの答えに完全に満足しているわけではありません.同じディスクロックですでに待機している他のスレッドがたくさんある場合、優先度のあるスレッドは長時間枯渇する可能性があります. それを避けるために、私はもっと考えました。おそらくディスクごとのロックではなく、条件変数とそれに関連するミューテックスの下ですべてを処理する必要があります。ただし、これで開始できることを願っています。