最近在弄 power daemon ,需要使用大量 thread , 並且不能讓這些 thread " free running " , 所以再次研究一下 pthread_cond_wait() & pthread_cond_timedwait() !
先來看看 pthread_cond_wait() 的說明吧 ! (下列 藍色文字擷取於 man 說明)
pthread_cond_wait() 的動作會先取得 cond 的內容 , 然後 unlock 讓 ptherad_cond_signal() 可以更改 cond 的內容,接著再 lock , 並判斷是否需要繼續 ptherad , 如果沒有就 unlock 並停下 pthread, 相反就 lock 且接著 pthread 的內容.
pthread_cond_wait(mutex, cond):
value = cond->value; /* 1 */
pthread_mutex_unlock(mutex); /* 2 */
pthread_mutex_lock(cond->mutex); /* 10 */
if (value == cond->value) { /* 11 */
me->next_cond = cond->waiter;
cond->waiter = me;
pthread_mutex_unlock(cond->mutex);
unable_to_run(me);
} else
pthread_mutex_unlock(cond->mutex); /* 12 */
pthread_mutex_lock(mutex); /* 13 */
value = cond->value; /* 1 */
pthread_mutex_unlock(mutex); /* 2 */
pthread_mutex_lock(cond->mutex); /* 10 */
if (value == cond->value) { /* 11 */
me->next_cond = cond->waiter;
cond->waiter = me;
pthread_mutex_unlock(cond->mutex);
unable_to_run(me);
} else
pthread_mutex_unlock(cond->mutex); /* 12 */
pthread_mutex_lock(mutex); /* 13 */
我們再看看 pthread_cond_signal() 的動作吧.
首先會先 lock , 如果 lock 失敗會繼續等在 lock 階段, lock 成功會更動 cond 內容,並且叫醒 pthread. 然後 unlock 讓 pthread 可以繼續執行.
pthread_cond_signal(cond):
pthread_mutex_lock(cond->mutex); /* 3 */
cond->value++; /* 4 */
if (cond->waiter) { /* 5 */
sleeper = cond->waiter; /* 6 */
cond->waiter = sleeper->next_cond; /* 7 */
able_to_run(sleeper); /* 8 */
}
pthread_mutex_unlock(cond->mutex); /* 9 */
說這麼多 ,來個範例吧 :
下列兩個範例 , 一個是 pthread 本身 , 做完事情後等著 pthread_cond_signal() 來進行離開.
所以可以看到 pthread 執行時先 lock , 最後停在 pthread_cond_wait() . 等另外 function
送出 pthread_cond_signal() , pthread 就會繼續執行,並且離開 pthread.
{
pthread_mutex_lock(&thread_mutex);
/* Loop forever */
for ( ps_thread_status = 1; ps_thread_status; )
{
//---- TO DO.
pthread_cond_wait(&thread_cond, &thread_mutex);
} /* End of for() */
pthread_mutex_unlock(&thread_mutex);
pthread_exit ( 0 );
}
void ps_thread_destory(void)
{
ps_thread_status = 0;
pthread_cond_signal(&thread_cond); // force weakup thread , then stop itself.
pthread_join(thread_ps_id, NULL); // wait for thread end.
pthread_mutex_destroy(&thread_mutex);
pthread_cond_destroy(&thread_cond);
}
{
ps_thread_status = 0;
pthread_cond_signal(&thread_cond); // force weakup thread , then stop itself.
pthread_join(thread_ps_id, NULL); // wait for thread end.
pthread_mutex_destroy(&thread_mutex);
pthread_cond_destroy(&thread_cond);
}
如果想要讓 pthread 暫停一段時間 後繼續執行 , 那就需要 pthread_cond_timedwait() 了.
範例如下 , 每一秒執行 for loop 一次.(紅色部分 是修改)
利用 pthread_cond_timedwait() return 的 value , 就可以判別是 timeout 還是被 signal 叫醒.
{
pthread_mutex_lock(&thread_mutex);
/* Loop forever */
for ( ps_thread_status = 1; ps_thread_status; )
{
//---- TO DO.
gettimeofday(&tv, &tz);
ts.tv_sec = tv.tv_sec + 1 ;
ts.tv_nsec = tv.tv_usec*1000;
retval = pthread_cond_timedwait(&thread_cond, &thread_mutex, &ts);
if ( retval == ETIMEDOUT)
{
//==== time out.
//---- TO DO.
}
else
{
//==== Got signal.
//---- TO DO.
}
} /* End of for() */
pthread_mutex_unlock(&thread_mutex);
pthread_exit ( 0 );
}
這樣的架構下就可以控制 pthread 進行一些流程控制了.
沒有留言:
張貼留言