Я думаю, что ваше подозрение обосновано. Код должен выглядеть как
void do_callback(boost::unique_lock<boost::mutex>& lock)
{
if(callback && !done)
{
boost::function<void()> local_callback=callback;
callback=boost::function<void()>;
relocker relock(lock); // unlock mutex?
local_callback();
}
}
или даже
void do_callback(boost::unique_lock<boost::mutex>& lock)
{
if(callback && !done)
{
boost::function<void()> local_callback=boos::move(callback);
relocker relock(lock); // unlock mutex?
local_callback();
}
}
Once Boost.Function будет поддерживать семантику перемещения.
У этого есть еще некоторые проблемы, так как другой поток может вызвать set_wait_callback, поэтому обратный вызов может быть переназначен и могут быть вызваны два обратных вызова. Кажется, что требуется дополнительное состояние, чтобы указать, что обратный вызов уже выполнен.
void do_callback(boost::unique_lock<boost::mutex>& lock)
{
if(callback && ! callback_done && !done)
{
boost::function<void()> local_callback=callback;
callback_done=true;
relocker relock(lock); // unlock mutex?
local_callback();
}
}
Кстати, set_wait_callback не является поточно-ориентированным.
template<typename F,typename U>
void set_wait_callback(F f,U* u)
{
callback=boost::bind(f,boost::ref(*u));
}
и должен быть защищен
template<typename F,typename U>
void set_wait_callback(F f,U* u)
{
boost::lock_guard<boost::mutex> lock(mutex);
callback=boost::bind(f,boost::ref(*u));
}
Пожалуйста, не могли бы вы создать билет Trac для Boost Thread, чтобы эта проблема не была потеряна?