0

I have a loop which calls pthread_join but the order of the loop does not match the order of thread's termination. how can i monitor thread completion then call join?

for ( int th=0; th<sections; th++ ) 
{
    cout<<"start joining "<<th<<endl<<flush;
    result_code = pthread_join( threads[th] , (void**)&status); 
    cout<<th<<" join error "<<strerror(result_code)<<endl<<flush;
    cout<<"Join status is "<<status<<endl<<flush;
}

This is my solution, which seems to maximize multi-threading throughput by serving the first done thread . This solution does not depend on pthread_join loop order.

    // loop & wait for the first done thread

    std::bitset<Nsections> ready;
    std::bitset<Nsections> done;
    ready.reset(); 
    for (unsigned b=0; b<sections; b++) ready.flip(b);
    done = ready;

    unsigned currIdx = 1;       
    int th = 0;
    int th_= 0;
    int stat;

    while ( done.any() )
    {

        // main loops waiting for 1st thread to complete.
        // completion is checked by global vector
        // vStatus (singlton write protected)
        // and not by pthread_exit returned value,
        // in ordder to maximize throughput by 
        // post processig the first 
        // finished thread.

        if ( (obj.vStatus).empty() ) { Sleep (5); continue; }

        while ( ready.any() )
        {
            if ( sections == 1 ) break;

            if ( !(obj.vStatus).empty() )
            {
                if ( currIdx <= (obj.vStatus).size() )
                {
                    th_ = currIdx-1;

                    std::string s =
                    ready.to_string<char,std::string::traits_type,std::string::allocator_type>();
                    cout<<"checking "<<th_<<"\t"<<s<<"\t"
                        <<(ready.test(th_)?"T":"F")<<"\t"<<(obj.vStatus)[th_].retVal <<endl;        

                    if ((obj.vStatus)[th_].retVal < 1)
                    {
                        if (ready.test(th_))
                            { 
                            th=th_; 
                            ready.reset(th); 
                            goto retry;
                        }
                    }
                }
            }
            Sleep (2);

        } // while ready


        retry:
        cout<<"start joining "<<th<<endl<<flush;
        result_code = pthread_join( threads[th] , (void**)&status); 

        switch (result_code)
        {
            case EDEADLK: goto retry; break;
            case EINVAL:  
            case ESRCH:  
            case 0: 
                      currIdx++; 
                      stat = status->retVal;
                      free (status);
                      done.reset(th);

                      std::string s =
                    done.to_string<char,std::string::traits_type,std::string::allocator_type>();
                    cout<<"joined thread "<<th<<"\t"<<s<<"\t"
                        <<(done.test(th)?"T":"F")<<"\t"<<stat <<endl;

                      while (true)
                      {
                        auto ret=pthread_cancel ( threads[th] ) ;
                        if (ret == ESRCH) { netTH--; break; }
                        Sleep (20);
                      }
                      break;
        }
BNR
  • 55
  • 1
  • 8
  • That may require you checking some flags. Why not use higher levels of abstractions such as `std::async` and any other mechanism that produces a `std::future`? See http://stackoverflow.com/questions/10890242/get-the-status-of-a-stdfuture – WhiZTiM Apr 16 '17 at 19:17
  • when the thread is complete set a bool. check said bool in a loop in main thread – DanielCollier Apr 16 '17 at 19:18
  • Thanks Daniel, but I think the bool var which is an arg in the pthread_create isn't updated before termination – BNR Apr 16 '17 at 21:02
  • If @WhiZTiMs suggestion isn't suitable for some reason, you might want to consider removing the C++ tag and explicitly state that you want a solution that depends only on POSIX or pthreads (as the case might be). – Michael Burr Apr 17 '17 at 20:15

1 Answers1

0

How can I monitor thread completion then call join ?

By letting join detect the completion. (i.e. do nothing special)

I have a loop which calls pthread_join but the order of the loop does not match the order of thread's termination.

The order of the loop does not matter.

a) thread[main] calling thread[1].'join' will simply be suspended until thread[1] exits. After that, thread[main] will be allowed to continue with the rest of the loop.

b) When thread[2] terminates before thread[1], thread[main] calling thread[2].join simply returns immediately. Again, thread[main] continues.

c) The effort to ensure thread[1] terminates prior to thread[2] (to match the loop sequence) is a surprisingly time consuming effort, with no benefit.

Update in progress ... looking for code I thought I have already submitted.

Cameron
  • 1,049
  • 12
  • 24
2785528
  • 5,438
  • 2
  • 18
  • 20
  • "The order of the loop does not matter" - that depends on the requirements of the program. For example, the thread performing the joins might want to collect the work of completed threads and process it as it's done (for example to display intermediate results to a user) instead of blocking on some arbitrary thread that might not finish for a long while. – Michael Burr Apr 17 '17 at 20:12