ich durch meine STL-Implementierung las (Standard-Ausgabe g++ 4.6.2
) und kam in diesem Stück Race-Bedingung innerhalb von condition_variable
:condition_variable timed_wait Implementierung korrekt
template<typename _Rep, typename _Period>
cv_status
wait_for(unique_lock<mutex>& __lock,
const chrono::duration<_Rep, _Period>& __rtime)
{
return wait_until(__lock, __clock_t::now() + __rtime);
}
Da __clock_t
ein std::chrono::system_clock
ist, sind wir auf die gebunden Launen von Dingen wie NTP (wenn die Uhr um einen Tag nach __clock_t::now() + __rtime
zurückgeschoben wird, dann werden wir einen Tag warten).
Die C++ Standard (30.5.1) erscheint es richtig:
Effekte: als ob
return wait_until(lock, chrono::steady_clock::now() + rel_time);
der Boost-condition_variable
Implementierung hat die gleiche Problem:
template<typename duration_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
{
return timed_wait(m,get_system_time()+wait_duration);
}
In der Tat, die zugrunde liegende pThreads Implementierung scheint das Problem zu sein:
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);
weil abstime
als angegeben "Systemzeit" keine monotone Uhr.
Also meine Frage ist: Wie würde man so etwas wie std::condition_variable::wait_for
korrekt implementieren? Gibt es eine bestehende Implementierung, die das richtig macht? Oder fehlt mir etwas?
Hinweis: Intern verwendet 'pthread_cond_timedwait'' gettimeofday', was ein Fehler ist, wenn Sie in der von Ihnen angegebenen Zeit ein Timeout setzen möchten: http://sourceware.org/git/?p=glibc.git;a=blob; f = nptl/pthread_cond_timedwait.c; h = 7278ec45b0eb0b48be50fe832fcd17ae988dca27; hb = HEAD –
Sie sind wahrscheinlich gezwungen, einen anderen Timer-Thread zu verwenden, der eine monotone Uhr verwendet, und weckt dann Ihren Kellner auf, wenn er abläuft, bevor der Kellner ihn abbricht. – jxh
Wenn ich so weit gehen muss (was ich ernsthaft hoffe, dass ich es nicht tue), würde ich lieber ein Dreh warten in meiner 'wait_for' Funktion (es sieht so aus, als hätte mein' sleep_for' dieses Problem nicht, wie 'nanoschlaf 'hat nicht das selbe Problem, weil' CLOCK_MONOTONIC' korrekt verwendet wird. –