|
Boost Users : |
Subject: Re: [Boost-users] Race condition with Boost::Thread
From: Craig Henderson (cdm.henderson_at_[hidden])
Date: 2009-07-29 10:45:27
2009/7/29 Craig Henderson <cdm.henderson_at_[hidden]>
>
>
> 2009/7/29 Rob Yull <ryull_at_[hidden]>
>
>> Ive been writing a thread pool class as kind of an experiment with
>> boost.threads, boost.bind, and boost.function. The code below is the worker
>> thread, that will eventually pull jobs from a queue, execute them, then look
>> and see if there is another job in the queue. I think Ive got an
>> interesting race condition. The problem Im having is when the class goes
>> out of scope. Im getting an access violation from the run() member
>> function (which is function being run by m_Thread). Right now, run() is
>> just entering and leaving (no actual queue checking). By the time run() is
>> getting executed, the class is starting to execute the destructor. I
>> thought that having the join() call in the destructor should allow the
>> thread to finish before the class data is destroyed. In Visual Studio
>> 2005s debugger, when it is getting to run(), it looks like the object has
>> already been destroyed (this = 0x7fffffff), so the access violation is
>> coming from the assignment to the m_Running member variable. If I take out
>> the assignment, and run the debug, when it is entering run(), the this
>> pointer is still showing as invalid, but the function completes and ends up
>> back at the join() in the destructor, where the this pointer in the
>> destructor is valid again. So as far as the destructor seems to be
>> conserned, the class hasnt been destroyed yet, but as far as the member
>> class is, it has been destroyed already.
>>
>>
>>
>> If I do pad some instructions/time before the class goes out of scope,
>> run() executes just fine (this pointer is valid). I have also tried moving
>> the creation of m_Thread outside of the constructor to a separate member
>> function call, but the result is the same.
>>
> [sorry for the partial post earlier]
Hi Rob,
The WorkerThread object is going out of scope before the run() is executed
in the secondary thread. You need to synchronise the startup/shutdown down.
I suggest you move the m_Running=true; into the run() [the thread isn't
running until run() is called, afterall], and in the dtor, wait for the
thread to start before calling join.
class WorkerThread
{
public:
typedef boost::function<void ()> JobType;
WorkerThread()
{
m_Thread = boost::thread(boost::bind(&WorkerThread::run,
boost::ref(this)));
}
~WorkerThread()
{
while (!m_Running)
;
m_Thread.join();
m_Running = false;
}
const bool isRunning() const
{
return m_Running;
}
private:
volatile bool m_Running;
boost::thread m_Thread;
void run()
{
m_Running = true;
BOOST_ASSERT(isRunning());
}
private:
WorkerThread(const WorkerThread& rhs);
WorkerThread& operator = (const WorkerThread& rhs);
};
Regards
-- Craig
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net