I have the following task:
There is a pool of equivalent resources (e.g. input slots) and a set of actions to be performed with this pool.
Each action is executed in a separate thread.
Each action requires different number of input slots available.
I want to use something like semaphores for the following task:
All action threads are executed simultaneously
The action is performed when the required number of input slots are free to use
Slots are set free when the action is finished
I can’t use regular semaphore because it’s impossible to set semaphore negative initial value or decrement the value until it becomes negative
So I need “semaphore” with the function WaitMultiple(int N), which does smth like “wait until resource value reaches N”
Any suggestions how I can solve it?
I prefer thread block/release, I can not afford active loops
I’m not sure that semaphores are useful here.
I think you can do this with a thread pool and some code in a CS/mutex protected section. Put the actions in a collection, (list/queue/stack, whatever is best for your dispatching algorithm), and initialize a slot-count. Then, and whenever slots are freed by completing actions, enter the CS and decide which action/s to execute given the current slot-count. Submit these actions to a thread pool, decrement the slot-count appropriately and exit the CS.
‘Slot-count’ could be a simple integer or a collection count of some complex class – doesn’t really matter.
Whenever the free slot count increases, you have to make a decision about which action to dispatch onto the threadpool. You will need some sort of algorithm since it seems possible that a slot-release may make it possible to run more than one action – do you maybe run the action with the highest slot-requirement first?
I don’t see any need for a separate dispatcher thread and certainly not any CPU loops! I fear that any solution based on thread/s trying to accumulate a slot target by waiting on some synchro object for available slots would be a deadlock risk – many threads could be stuck with partial slot counts and so prevent forward progress. Also, you would be unable to tweak the algorithm to, say, prevent actions with a high slot-requirement being starved.