Android NDK - pthread_cancel alternatives

    Android's NDK doesn't support pthread_cancel due to the complexity it brings to the table. So is there any way to request a native thread to quit? This is mostly a requirement for a relatively long living thread, usually sleeping for a while in a loop. Threads in gaming applications often wake up to check network stats etc. So how can they be terminated (say when the application is pushed to background or when it is paused)?

      The simple solution is to keep checking for a boolean variable and exit accordingly.

void* networkStatThread(void* arg) {

       while ( true ) {

             usleep( duration );

             bool exitThread = false;
  
             pthread_mutex_lock(&myMutex);
             exitThread = mQuitThread;
             pthread_mutex_unlock(&myMutex);

            if ( exitThread ) {
                 beak;
            }

            // Perform Timeout Operations
        
       }

       return NULL;
}

    The caller thread just has get exclusive access to mQuitThread and set it to true.


void* finalizerThread(void* arg) {

             pthread_mutex_lock(&myMutex);
             mQuitThread = true;
             pthread_mutex_unlock(&myMutex);

}

  The only downside is that the thread doesn't quit immediately on demand, instead sleeps out the entire duration. This might not be a big deal in most of the cases but there might be cases where the thread sleeps for a long duration primarily to ensure it doesn't wake up often and burn cycles. So in those cases, the thread takes a longer time to quit. So how to ensure on demand thread clean up? pthread_cancel would have helped but thats not supported in Android NDK. Well, pthread_cond_timedwait comes to the rescue.

void* networkStatThread(void* arg) {

    while ( true ) {

       pthread_mutex_lock(&myMutex);
       int ret = pthread_cond_timedwait(&myCond, &myMutex, &myTimeSpec);
       pthread_mutex_unlock(&myMutex);

       if ( ret == ETIMEDOUT ) {
            // Perform Timeout Operations
       } else {
           // This thread has been signaled before the timeout.
           break;
      }

    }

    return NULL;
}

In this case, the caller thread just has to notify on the condition and that would serve as an immediate wakeup, irrespective of the current sleep duration.

void* finalizerThread(void* arg) {

             pthread_mutex_lock(&myMutex);
             pthread_cond_signal(&myCond);
             pthread_mutex_unlock(&myMutex);

}

pthread_cond_broadcast could be used when dealing with multiple native threads.

No comments: