I'm having a weird problem with a threaded class using Boost::threads. Here is a brief summary of what I'm doing:
A routine creates a bunch of objects that are made up of a handler class with a private data member that is a shared pointer to a base class that forms an inheritance tree. I'm fairly confident this routine is working correctly, and not part of the problem.
I then call a method of the handler class (startUpdate) which creates a new instance of my threaded class. Here's the threaded class code:
class Sensor_Thread
{
public:
//constructor (creates thread and binds the update function to it
Sensor_Thread (const Ptr<Sensor_Base> & theSensor): m_stoprequested (false),
s (theSensor),
m_thread (boost::bind (&Sensor_Thread::update, this)) { }
//default null constructor, shouldn't ever be used
Sensor_Thread (): m_stoprequested (true),
m_thread (),
s (NULL) { }
//destructor (automatically joins the thread as per RAII principles)
~Sensor_Thread () { m_stoprequested = true; m_thread.join (); }
private:
volatile bool m_stoprequested;
boost::mutex m_mutex;
boost::thread m_thread;
Ptr<Sensor_Base> s;
void update ();
};
(the "Ptr" class there is my shared pointer class... I'm fairly confident it works correctly because I originally got it from a C++ textbook...)
The update function:
void Sensor_Thread::update ()
{
//make sure we actually have a sensor attached...
if (s) {
// set up structure for sleeping
struct timespec time;
while (!m_stoprequested)
{
boost::mutex::scoped_lock lock(m_mutex);
s->update ();
time.tv_sec = s->updateInterval / 1000;
time.tv_nsec = (1000 % s->updateInterval) * (1000 * 1000);
nanosleep (&time, NULL);
}
}
}
This runs indefinitely until another trigger in the driver calls stopUpdate and the threaded_class is destroyed.
The weirdness: On my development box, which is OS X 10.6, using darwin gcc 4.2.1, it works fine, exactly as expected.
This is meant to run on an embedded server with debian linux and an ARM processor. I have a cross-compile toolchain provided by the manufacturer of the embedded system, and when I use this to cross-compile, I get a seg fault. Through debugging I've found this seg fault occurs when s->update () is called (or ANY other attempt to dereference the shared pointer and do something to it). However, if I introduce a slight delay, say by adding "sleep(1);" before starting the while loop in my Sensor_Thread::update function, it works flawlessly.
To my mind, this seems to imply that the system is trying to dereference the shared pointer s before it's fully or adequately initialized? The sleep(1) work-around makes it work, but still, that seems extremely weird to me. If the threaded class' shared pointer is initialized during the constructor, shouldn't it be ready before the update function ever gets called? Or does the creation of the boost::thread mean that the update function happens simultaneously to the initialization of the shared pointer owned by the threaded class? Is there any cleaner way than the "sleep" hack to make SURE the shared pointer is initialized before the update function is called?
Thanks!!!