I'm stuck with a problem I quite don't understand and that involve either
boost::future/promise or tbb::concurrent_queue,
or my understanding of using both.
I think there is a high probability that someone here will point to the
problem, but I will report too to the tbb forum
Some context:
- I'm using VS2012 Update 2
- it's 32 bit DEBUG mode
- I use Boost.Thread V4 (in CMake I set "add_definitions(
-DBOOST_THREAD_VERSION=4 )" to force it )
- I use TBB 4.1 Update 2
I've setup a test (using GTest) which reproduce the problem:
############
int TRUC = 42;
TEST( Test_WorkQueue, future_promise_shared_work )
{
WorkQueue work_queue;
// I'm doing this like that because it reflect the use case I have,
// I didn't find another way to have the promise alive in a
container which don't allow move semantic
auto do_some_work = [&]()-> boost::future
{
struct K
{
boost::promise promise;
void foo()
{
promise.set_value( &TRUC );
}
};
auto object_ptr = std::make_shared<K>(); // D:
work_queue.push( [=]
{
object_ptr->foo();
});
return object_ptr->promise.get_future();
};
auto ft_value = do_some_work();
work_queue.execute();
auto value = ft_value.get();
ASSERT_EQ( &TRUC, value ); // this fails, value == 0xfeeefeee
}
##########
My WorkQueue type use tbb::concurrent_queue and is defined as:
##########
class WorkQueue
{
public:
template< class WorkTask >
void push( WorkTask&& task )
{
m_task_queue.push( std::forward<WorkTask>( task ) );
}
/** Execute all the work queued until now. */
void execute()
{
if( m_task_queue.empty() )
return;
bool end_of_work = false;
m_task_queue.push( [&]{ end_of_work = true; } );
std::function work;
while( !end_of_work && m_task_queue.try_pop( work ) )
{
work();
}
}
private:
mutable tbb::concurrent_queue< std::function > m_task_queue;
};
############
It's basically a simple wrapper around the concurrent_queue, but maybe the
execute() code have an impact.
THE PROBLEM:
The test fails.
value == 0xfeeefeee as soon as the get() call is done.
Using the debugger, I can't figure where the data is lost. It seem that
everything is correct until when all
the hierarchy of function call returns the result...which is different and
wrong once out of the function.
I first wrote this test with std::vector< std::function >
instead of the concurrent queue to check if it was boost::future/promise
which was not working well with Boost.Thread V4.
With the vector instead of concurrent_queue, the code works perfectly.
Does someone have an idea what is going on?
Joel Lamotte