前置き
- 内製ツールでpthread_cond_timedwaitを使って数秒waitさせたい処理が、実はwaitできてなかった
どういうこと?
- プリプロセッサシンボルの定義状態から、
pthread_cond_timedwait
とpthread_cond_timedwait_relative_np
とを使い分ける処理が存在 - 使い方のノリがほぼ一緒であった
- Androidの64bit対応する折に、
error: '::pthread_cond_timedwait_relative_np' has not been declared
となり、releative_npの方を使わないようにする対応が必要となった - そのまま処理を流用したら、なぜか全くwaitしてくれなくなった
こんなイメージ
XXXThread.cpp
# if XXX //今まではこっちが通るようにシンボル定義してあった
struct timespec ts;
long sec = timeoutInUsec / 1000000;
long mod_sec = timeoutInUsec % 1000000;
ts.tv_sec = sec;
ts.tv_nsec = mod_sec * 1000;
int result = ::pthread_cond_timedwait_relative_np(&m_signal, &m_mutex, &ts);
# else //★今回の対応で通るようになったスコープはコチラ
struct timespec ts;
long sec = timeoutInUsec / 1000000;
long mod_sec = timeoutInUsec % 1000000;
time_t now = 0;
ts.tv_sec = sec + time(&now);
ts.tv_nsec = mod_sec * 1000;
int result = ::pthread_cond_timedwait(&m_signal, &m_mutex, &ts);
# endif
なんでか?
pthread_cond_timedwait_relative_np
は名前の通り、相対時間を入力にwaitしてくれる。
対して pthread_cond_timedwait
は絶対日時を入力にwaitしてくれる。
つまり、上記のイメージの処理だと、 nsecの指定を ts.tv_nsec = mod_sec * 1000;
としているが、これは相対時間なので、ほぼほぼ実時間未満の数値が入り、想定している時間でwaitできてなかった。
つまりこんな感じで修正すれば最終的にOKだった
- clock_gettimeでnsecの精度で現在時刻を取得するようにした
- 現時刻をベースにwaitしたい時間を加算してあげるようにした
- 桁あふれを考慮した
XXXThread.cpp
# if XXX //今まではこっちが通るようにシンボル定義してあった
struct timespec ts;
long sec = timeoutInUsec / 1000000;
long mod_sec = timeoutInUsec % 1000000;
ts.tv_sec = sec;
ts.tv_nsec = mod_sec * 1000;
int result = ::pthread_cond_timedwait_relative_np(&m_signal, &m_mutex, &ts);
# else //★今回の対応で通るようになったスコープはコチラ
struct timespec ts;
long sec = timeoutInUsec / 1000000;
long mod_sec = timeoutInUsec % 1000000;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += sec;
ts.tv_nsec+= mod_sec * 1000;
if (1000000000 <= ts.tv_nsec)
{
ts.tv_nsec -= 1000000000;
ts.tv_sec += 1;
}
result = ::pthread_cond_timedwait(&m_signal, &m_mutex, &ts);
# endif