
Hi all, I had a question about boost threads as im using them currently in a project. I've written a very simple implementation of what im trying to do and the result I get, but im having trouble understanding why: mytest.cpp: class A { public: A() {} ~A() {} virtual void worker() { std::cout << "I am A worker" << std::endl; } virtual A *factory() { std::cout << "Factory for A class called" << std::endl; return new A; } virtual void operator()() { std::cout << "Calling A operator()" << std::endl; worker(); } void threadcontroller() { boost::thread_group thre; for(;;) { std::cout << "I am in the A.threadcontroller() method" << std::endl; A *mea = factory(); mea->worker(); thre.create_thread(*mea); exit(0); } } }; class B: public A { public: B() {} ~B() {} virtual void worker() { std::cout << "I am B worker" << std::endl; } virtual void operator()() { std::cout << "Calling B operator()" << std::endl; worker(); } B *factory() { std::cout << "Factory for B class called" << std::endl; return new B; } }; int main() { B meb; meb.worker(); meb.threadcontroller(); } Output: $ ./mytest I am B worker I am in the A.threadcontroller() method Factory for B class called I am B worker Calling A operator() I am A worker The first output is from the meb.worker() call in main(), the second is from meb.threadcontroller. the thrid is the factory call from within threadcontroller, the forth is mea.worker() in thread controller, then the next 2 are from after the thread_group.create_thread() call. Once its in the thread it seems to revert to class A's methods. Now, i know if i overload the threadcontroller class in B it'd solve all my problems, but the real threadcontroller method is alot more complex and class A has about 6 sub classes so replicating the threadcontroller in each of the classes would be a little tedious. Have i stumbled across a bug, or is that how its supposed to work? Thanks in advance

On Sunday 10 February 2008 09:55, Paul J R wrote:
class A { public: A() {} ~A() {} virtual void worker() { std::cout << "I am A worker" << std::endl; } virtual A *factory() { std::cout << "Factory for A class called" << std::endl; return new A; } virtual void operator()() { std::cout << "Calling A operator()" << std::endl; worker(); } void threadcontroller() { boost::thread_group thre; for(;;) { std::cout << "I am in the A.threadcontroller() method" << std::endl; A *mea = factory();
I think you might need to call factory like "this->factory()"
the next 2 are from after the thread_group.create_thread() call. Once its in the thread it seems to revert to class A's methods.
Now, i know if i overload the threadcontroller class in B it'd solve all my problems, but the real threadcontroller method is alot more complex and class A has about 6 sub classes so replicating the threadcontroller in each of the classes would be a little tedious.
-- Frank

I thought that was expected behavior when you didn't declare factory virtual
in B, since the virtual jump table in A is overriding B's function table.
When I tried this, making B's factory virtual caused B's factory to get
called instead of A's.
On Feb 10, 2008 3:55 PM, Frank Mori Hess
On Sunday 10 February 2008 09:55, Paul J R wrote:
class A { public: A() {} ~A() {} virtual void worker() { std::cout << "I am A worker" << std::endl; } virtual A *factory() { std::cout << "Factory for A class called" << std::endl; return new A; } virtual void operator()() { std::cout << "Calling A operator()" << std::endl; worker(); } void threadcontroller() { boost::thread_group thre; for(;;) { std::cout << "I am in the A.threadcontroller() method" << std::endl; A *mea = factory();
I think you might need to call factory like "this->factory()"
the next 2 are from after the thread_group.create_thread() call. Once its in the thread it seems to revert to class A's methods.
Now, i know if i overload the threadcontroller class in B it'd solve all my problems, but the real threadcontroller method is alot more complex and class A has about 6 sub classes so replicating the threadcontroller in each of the classes would be a little tedious.
-- Frank
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- -Travis Savo CEO, Verse Studios web: http://www.verse-studios.com email: tsavo@verse-studios.com phone: 818.574.5009 blog: http://inverse.verse-studios.com linkedin: http://www.linkedin.com/in/travissavo

-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users- bounces@lists.boost.org] On Behalf Of Frank Mori Hess
<snap>
I think you might need to call factory like "this->factory()"
Notice that according to Paul's original message the right factory (the one in B) is being called. Output: $ ./mytest I am B worker I am in the A.threadcontroller() method Factory for B class called <--- The right factory is called, a B* is returned I am B worker <--- Calling worker() on that pointer calls B::worker(), definitely a B* Calling A operator() <--- Calling operator()calls A::operator(), why? I am A worker -delfin

On Monday 11 February 2008 04:49, Rob Desbois wrote:
On Feb 10, 2008 11:55 PM, Frank Mori Hess
wrote: I think you might need to call factory like "this->factory()"
I don't think so - in C++ AFAIU 'this->' is always implicit.
I just had a vague recollection of needing to explicitly use this-> in certain cases. Ah, I've found it... I was trying to access a protected member object in a base class from a derived class, and both of the classes were templates. -- Frank

Paul J R wrote:
mytest.cpp:
class A { public: A() {} ~A() {} virtual void worker() { std::cout << "I am A worker" << std::endl; } virtual A *factory() { std::cout << "Factory for A class called" << std::endl; return new A; } virtual void operator()() { std::cout << "Calling A operator()" << std::endl; worker(); } void threadcontroller() { boost::thread_group thre; for(;;) { std::cout << "I am in the A.threadcontroller() method" << std::endl; A *mea = factory(); mea->worker(); thre.create_thread(*mea); exit(0); } } };
class B: public A { public: B() {} ~B() {} virtual void worker() { std::cout << "I am B worker" << std::endl; } virtual void operator()() { std::cout << "Calling B operator()" << std::endl; worker(); } B *factory() { std::cout << "Factory for B class called" << std::endl; return new B; } };
int main() { B meb;
meb.worker(); meb.threadcontroller(); }
Hi Paul, Note that thread_group::create_thread(const boost::function0<void>&) takes a boost::function0<void> as an argument so in case you pass a functor like you do, boost::function will resolve to the operator() of the apparent pointer type (i.e. A::operator()). In order to make this work you need a way to construct a "pointer to member function" which takes into account the actual value of "this". So instead of thre.create_thread(*mea); You want: thre.create_thread(boost::bind(&A::operator(), mea)); For this you need to include boost/bind.hpp. In this case boost::bind will make a functor and when create_thread calls that functor, boost::bind will effectively call mea->operator(). Next thing, you don't want to call exit() right after you create the thread because once your main thread exits the other one will exit too (how soon depends on your OS, in my machine the thread doesn't even get to start before it is killed because the main thread is exiting). So you want to call thre.join_all(); so the main thread sleeps until all the threads are done. So my A::threadcontroller looks like this: void threadcontroller() { boost::thread_group thre; std::cout << "I am in the A.threadcontroller() method" << std::endl; A *mea = factory(); mea->worker(); thre.create_thread(boost::bind(&A::operator(), mea)); thre.join_all(); } Using this A::threadcontroller my output looks like this: I am B worker I am in the A.threadcontroller() method Factory for B class called I am B worker Calling B operator() I am B worker Which is what you want (I think). Also, one nice thing about using boost::bind is that you can use any method as the thread body (i.e. you can rename your operator() to dowork() if you want). Good luck, -delfin

On Feb 10, 2008 2:55 PM, Paul J R
Now, i know if i overload the threadcontroller class in B it'd solve all my problems, but the real threadcontroller method is alot more complex and class A has about 6 sub classes so replicating the threadcontroller in each of the classes would be a little tedious.
Have i stumbled across a bug, or is that how its supposed to work?
A *mea = factory(); mea->worker(); thre.create_thread(*mea); I think if you dereference a variable of type A* you get, and will always get, an object of type A. At compile-time the compiler won't know whether the A* will point to an A or B, which doesn't matter with
That's how it's supposed to work; in A::threadcontroller(): pointer/reference semantics but does matter when the *object* is being passed as the compiler must know how much stack space to reserve for it. In this case it only knows to reserve enough for an A instance. I think you may have to define a method in A and B, similar to this: virtual void spawn(boost::thread_group& thre, A* worker) { thre.create_thread(worker); } Override it in B but it should then take a B* not A*. There may be a better way but this is what sprung to mind first off. HTH --rob
participants (5)
-
Delfin Rojas
-
Frank Mori Hess
-
Paul J R
-
Rob Desbois
-
Travis Savo