I have multiple threads processing multiple files in the background, while the program is idle.
To improve disk throughput, I use critical sections to ensure that no two threads ever use the same disk simultaneously.
The (pseudo-)code looks something like this:
void RunThread(HANDLE fileHandle)
{
// Acquire CRITICAL_SECTION for disk
CritSecLock diskLock(GetDiskLock(fileHandle));
for (...)
{
// Do some processing on file
}
}
Once the user requests a file to be processed, I need to stop all threads — except the one which is processing the requested file. Once the file is processed, then I’d like to resume all the threads again.
Given the fact that SuspendThread is a bad idea, how do I go about stopping all threads except the one that is processing the relevant input?
What kind of threading objects/features would I need — mutexes, semaphores, events, or something else? And how would I use them? (I’m hoping for compatibility with Windows XP.)
The difficulty here isn’t priority as such, it’s the fact that you want a thread to back out of a lock that it’s holding, to let another thread take it. “Priority” relates to which of a set of runnable threads should be scheduled to run — you want to make a thread runnable that isn’t (because it’s waiting on a lock held by another thread).
So, you want to implement (as you put it):
Since you’re (wisely) using a scoped lock I would want to invert the logic:
Read up on condition variables — all recent OSes have them, with similar basic operations. They’re also in Boost and in C++11.
If it’s not possible for you to write a function
process_part_of_the_filethen you can’t structure it this way. Instead you need a scoped lock that can release and regain the disklock. The easiest way to do that is to make it a mutex, then you can wait on a condvar using that same mutex. You can still use the mutex/condvar pair and thethread_with_priorityobject in much the same way.You choose the size of “part of the file” according to how responsive you need the system to be to a change in priority. If you need it to be extremely responsive then the scheme doesn’t really work — this is co-operative multitasking.
I’m not entirely happy with this answer, the thread with priority can be starved for a long time if there are a lot of other threads that are already waiting on the same disk lock. I’d put in more thought to avoid that. Possibly there should not be a per-disk lock, rather the whole thing should be handled under the condition variable and its associated mutex. I hope this gets you started, though.