Virlym
Virlym

Reputation: 13

Which thread finishes with multithreading?

I am new to here and I hope I am doing everything right.

I was wondering how to find out which thread finishes after waiting for one to finish using the WaitForMultipleObjects command. Currently I have something along the lines of:

int checknum;
int loop = 0;
const int NumThreads = 3;

HANDLE threads[NumThreads];

WaitForMultipleObjects(NumThreads, threads, false, INFINITE);
threads[loop] = CreateThread(0, 0, ThreadFunction, &checknum, 0, 0);

It is only supposed to have a max of three threads running at the same time. So I have a loop to begin all three threads (hence the loop value). The problem is when I go through it again, I would like to change the value of loop to the value of whichever thread just finished its task so that it can be used again. Is there any way to find out which thread in that array had finished?

I would paste the rest of my code, but I'm pretty sure no one needs all 147 lines of it. I figured this snippet would be enough.

Upvotes: 1

Views: 103

Answers (2)

odinthenerd
odinthenerd

Reputation: 5562

I am away from my compiler and I don't know of an onlione IDE that works with windows but here is the rough idea of what you need to do.

const int NumThreads = 3;
HANDLE threads[NumThreads];
//create threads here
DWORD result = WaitForMultipleObjects(NumThreads, threads, false, INFINITE);
if(result >= WAIT_OBJECT_0 && result - WAIT_OBJECT_0 < NumThreads){
    int index = result - WAIT_OBJECT_0;
    if(!CloseHandle(Handles[index])){ //need to close to give handle back to system even though the thread has finished 
        DWORD error = GetLastError();
        //TODO handle error
    }
    threads[index] = CreateThread(0, 0, ThreadFunction, &checknum, 0, 0);
}
else {
    DWORD error = GetLastError();
    //TODO handle error
    break;
}

at work we do this a bit differently. We have made a library which wraps all needed windows handle types and preforms static type checking (though conversion operators) to make sure you can't wait for an IOCompletionPort with a WaitForMultipleObjects (which is not allowed). The wait function is variadic rather than taking an array of handles and its size and is specialized using SFINAE to use WaitForSingleObject when there is only one. It also takes Lambdas as arguements and executes the corresponding one depending on the signaled event.

This is what it looks like:

Win::Event ev;
Win::Thread th([]{/*...*/ return 0;});
//...

Win::WaitFor(ev,[]{std::cout << "event" << std::endl;},
        th,[]{std::cout << "thread" << std::endl;},
        std::chrono::milliseconds(100),[]{std::cout << "timeout" << std::endl;});

I would highly recommend this type of wrapping because at the end of the day the compiler optimizes it to the same code but you can't make nearly as many mistakes.

Upvotes: 0

Taylor Brandstetter
Taylor Brandstetter

Reputation: 3623

When the third parameter is false, WaitForMultipleObjects will return as soon as ANY of the objects is signaled (it doesn't need to wait for all of them).

And the return value indicates which object caused it to return. It will be WAIT_OBJECT_0 for the first object, WAIT_OBJECT_0 + 1 for the second, etc.

Upvotes: 2

Related Questions