boost.thread - class derivated from thread

L

Lars Uffmann

I'm a little at a loss here with the boost.thread documentation - I was
trying to find out if the thread class is destroyed upon thread
termination and I need to construct a new one for the next thread
execution of the same function, or if I can restart the old one. I
highly doubt a thread class can self-destruct, but I wanted to see when
the destructor was called. So I made a derived class myThread (or wanted
to) and I cannot seem to get the syntax for the constructor calling
thread::thread right.

So apart from looking for an answer as to how to re-execute a thread
that has ended, or if I have to delete the old one and create a new one,
I'm curious to know how to derive _any_ class from thread, with the
proper constructor syntax, equivalent to

----
class BOOST_THREAD_DECL thread : private noncopyable
{
public:
thread();
explicit thread(const function0<void>& threadfunc);
 
P

Phil Endecott

Lars said:
I'm a little at a loss here with the boost.thread documentation - I was
trying to find out if the thread class is destroyed upon thread
termination

No it's not; the lifetimes of the thread object and the thread itself
are independent. Either the thread can terminate before the object is
destroyed, or the object can be destroyed before the thread terminates.
and I need to construct a new one for the next thread
execution of the same function, or if I can restart the old one.

You should create a new thread object for each new thread.

If you want to "re-start" a thread, then you'll want to have a thread
body that has a loop:

void run() {
while (1) {
.. thread body ..
}
}

thread t(&run);

You'll then need some mechanism to pass new parameters to each iteration
of the loop. Typically you'll have a "work queue", protected by some
sort of mutex; the loop will wait until the queue is non-empty and pop
the next "work" from it.

It's much simpler to create a new thread for each "work", and I suggest
doing that unless you have some good reason not to.
I
highly doubt a thread class can self-destruct, but I wanted to see when
the destructor was called.

It's called when it goes out of scope, or when it's deleted if it was
allocated with new. Just like any other object.
So I made a derived class myThread (or wanted
to) and I cannot seem to get the syntax for the constructor calling
thread::thread right.

This interface uses Boost::Function, and I've always used it as shown below.
So apart from looking for an answer as to how to re-execute a thread
that has ended, or if I have to delete the old one and create a new one,
I'm curious to know how to derive _any_ class from thread, with the
proper constructor syntax, equivalent to

----
class BOOST_THREAD_DECL thread : private noncopyable
{
public:
thread();
explicit thread(const function0<void>& threadfunc);
----

What is BOOST_THREAD_DECL?

Untested:

class my_thread: public boost::thread
{
public:
my_thread(boost::function<void(void)> threadfunc):
boost::thread(threadfunc)
{}
};



A better place to ask these questions would be the boost users mailing list.


Phil.
 
L

Lars Uffmann

Phil said:
No it's not; the lifetimes of the thread object and the thread itself
are independent. Either the thread can terminate before the object is
destroyed, or the object can be destroyed before the thread terminates.

Thank you!

It's much simpler to create a new thread for each "work", and I suggest
doing that unless you have some good reason not to.

Hmm... my idea was to activate / deactivate a thread listening for
network traffic (in the background of a graphical application) upon user
input (toggle-button). Worked fine in the Widestudio implementation of
threads, I didn't think it made sense to re-create a new thread each
time I want to re-activate it, neither to have it running inactively in
the background when the user wants it to be deactivated.
This interface uses Boost::Function, and I've always used it as shown
below.

Thank you for that - the boost:function thing was what I was doing wrong
- I missed that that was part of the boost namespace, while in
thread.hpp the whole class definition happens within the namespace boost.
What is BOOST_THREAD_DECL?
Didn't bother to check :) - it's part of the boost thread library.
Untested:
Untested or not, it works :)
A better place to ask these questions would be the boost users mailing
list.
Well - if boost is going to be integrated into the next C++ standard, I
hope I can avoid subscribing to yet another mailing list ;)

Thank you again & Best Regards,

Lars
 
L

Lars Uffmann

Okay, now I know what annoys the heck out of me about this thread
behaviour: If I let the user click a button to deactivate the thread, I
send a signal to it so it terminates, and then I have a friggin race
condition :(

The thread is listening for UDP traffic, so I send it an "end of stream"
UDP-packet (self defined, data just "-1"), and now, because I have to
also delete this thread so I can create a new one, the next time one is
needed, I have to wait for the thread state to be not running and not
waiting anymore :/

Since I know there's usually lots of brainpower and developed thoughts
behind such things, by people with far more experience than myself,
maybe someone knows what the reasoning behind this design was..

And yes, I guess I'll have to join the boost users mailing list.

Best Regards,

Lars
 
L

Lars Uffmann

Can I deliberately destroy a boost:thread object (without calling join()
ever) once I am done starting the thread of execution? Documentation
almost seems to say so: "The converse is also possible; if a thread
object is destroyed without join() having first been called, the thread
of execution continues until its initial function completes."

Or is that undefined behaviour in some implementations of boost?

TIA,

Lars
 
P

Phil Endecott

Lars said:
Hmm... my idea was to activate / deactivate a thread listening for
network traffic (in the background of a graphical application) upon user
input (toggle-button).

So you want to stop and resume a thread? I think you need a boolean,
and to test it periodically inside the thread. If it's set, wait on a
condition until it is cleared.
Well - if boost is going to be integrated into the next C++ standard

The thread and related classes proposed for C++0x are described in
N2447. If you're using the current Boost SVN HEAD version, you're using
something similar. But the current released Boost.Threads is rather
different. It's definitely not true to say that "boost is going to be
integrated into the next C++ standard", and the people who can best
answer your questions about Boost are not in this newsgroup.


Phil.
 
P

Phil Endecott

Lars said:
Okay, now I know what annoys the heck out of me about this thread
behaviour: If I let the user click a button to deactivate the thread, I
send a signal to it so it terminates, and then I have a friggin race
condition :(

The thread is listening for UDP traffic, so I send it an "end of stream"
UDP-packet (self defined, data just "-1"),

You need thread cancellation. No, it's not in Boost.Thread, or in
N2447. What platform are you using? But without cancellation, you're
doing the right thing.
and now, because I have to
also delete this thread so I can create a new one

Why do you have to wait for the first thread to terminate before
starting another one?
Since I know there's usually lots of brainpower and developed thoughts
behind such things, by people with far more experience than myself,
maybe someone knows what the reasoning behind this design was..

What aspect of the design are you questioning?


Phil.
 
L

Lars Uffmann

Phil said:
You need thread cancellation. No, it's not in Boost.Thread, or in
N2447. What platform are you using? But without cancellation, you're
doing the right thing.

Right now, platform is WinXP, but I was looking forward to maybe migrate
to Linux eventually. I guess since what I'm doing works fine and you
agree with it, I'll keep it that way :)
Why do you have to wait for the first thread to terminate before
starting another one?

Well - matter of design as I migrated it from WideStudio, related to my
limited unterstanding of threads. I had a global variable pointing to my
thread (no real multithreading needed, just the network traffic handler
in parallel to the wxWidgets GUI event handler). So I was initializing
the thread once in my wxApp::OnInit, and then doing a thread::Execute
whenever the user told the software to start listening, and send that
end of stream signal when the user clicked the "Stop Listening" button.
I would need the global variable as a handle to restart the thread. If -
as you replied in the other post - I can just destroy the thread object
after initial start of thread of execution, I guess I don't really need
the global variable anymore anyways.
What aspect of the design are you questioning?

That a thread cannot be restarted, but instead has to be destroyed and
reconstructed.


Best Regards,

Lars
 
J

James Kanze

Can I deliberately destroy a boost:thread object (without
calling join() ever) once I am done starting the thread of
execution?

Yes, but this may have unintentional implications with regards
to the thread state. (This "feature" is probably the biggest
defect in Boost threads. But it's easy to work around.)

You should decide, up front, at creation, whether you want to
use joinable threads, or detached threads. (From what you've
described so far, it sounds like joinable.) In Boost (at least
the last version I looked at), destructing the creating thread
object before having joined makes the thread detached. If you
want a detached thread, just write a small function which you
call to start it---the boost::thread object is a local variable
in the function, and will be destructed when you return from the
function. If you want joinable threads, I'd wrap the thread
class in my own thread class, which would probably cause an
assertion failure if the destructor was called before the thread
was joined.

In your case, I think you probably should allocate the wrapped
thread dynamically; when you get the command to terminate it,
you do whatever is necessary so that it terminates, then join,
and only then delete the wrapped thread object (which in turn
would delete the boost::thread).

Alternatively, if you really only want a single thread, which
stops and starts, you should probably use boost::condition,
e.g.:

// in class, of course...
boost::mutex myMutex ;
boost::condition myCond ;
bool myIsActive ;

// called by external thread...
void activate()
{
boost::mutex::scoped_lock
l( myMutex ) ;
myIsActive = true ;
myCond.notify_all() ;
}

void deactivate()
{
boost::mutex::scoped_lock
l( myMutex ) ;
myIsActive = false ;
// do something to trigger passage through
// checkActivate() (send empty message, etc.)?
// This part could actually occur after the lock has
// been released.
}

// called by the thread itself, from time to time
void checkActivate()
{
boost::mutex::scoped_lock
l( myMutex ) ;
while ( ! myIsActive ) {
myCond.wait( l ) ;
}
}
 
Y

Yannick Tremblay

That a thread cannot be restarted, but instead has to be destroyed and
reconstructed.

I am not sure why you'd want the parent thread to restart another
thread. I fail to grasp your design.

See threads as multiple workers in a company. All of them have an
inbox for work-to-do. If there's no work to do, the worker sit idle
waiting for stuff in its inbox. (this translate to a
boost::condition::wait ).

Stopping and restarting threads is not really needed in this
abstraction.

Sure, you can always destroy and recreate which is the equivalent of
sack and rehire workers.

Yannick
 
L

Lars Uffmann

Yannick said:
I am not sure why you'd want the parent thread to restart another
thread. I fail to grasp your design.

See threads as multiple workers in a company. All of them have an
inbox for work-to-do. If there's no work to do, the worker sit idle
waiting for stuff in its inbox. (this translate to a
boost::condition::wait ).

I wanted the worker to sit idle, yes. Well, actually I wanted to send
him home to enjoy his freetime, and call him back to work when I need
him again. Thus the restart() :)
I didn't (and still don't) see a point in keeping a thread active in the
background (but doing nothing) if the only purpose of this thread is to
listen for certain network traffic, and the user explicitely switched
off that listen interface. In that case I wanted the thread to stop, and
not take up even 1 cpu cycle until the user wants it resumed.

Is boost::condition::wait really a better approach? Let's say some bug
affects the condition unwanted, that would "trigger" my thread execution
again when I don't want it to. It's like leaving the car but with the
engine idling. If you're unlucky, something unexpected makes the forward
gear jump in, resulting in some really bad things happening...

Best Regards,

Lars
 
J

James Kanze

I wanted the worker to sit idle, yes. Well, actually I wanted to send
him home to enjoy his freetime, and call him back to work when I need
him again. Thus the restart() :)
I didn't (and still don't) see a point in keeping a thread active in the
background (but doing nothing) if the only purpose of this thread is to
listen for certain network traffic, and the user explicitely switched
off that listen interface. In that case I wanted the thread to stop, and
not take up even 1 cpu cycle until the user wants it resumed.

I'm not sure what state you want to see the thread in. On most
systems today, once a thread has exit'ed, there's no way of
restarting it. And of course, a thread in a wait on a condition
takes 0 CPU time until someone wakes it up.
Is boost::condition::wait really a better approach? Let's say
some bug affects the condition unwanted, that would "trigger"
my thread execution again when I don't want it to. It's like
leaving the car but with the engine idling. If you're unlucky,
something unexpected makes the forward gear jump in, resulting
in some really bad things happening...

I'm afraid I don't see the difference. If someone starts a
thread when it's not wanted, you have a problem.
 
L

Lars Uffmann

James said:
I'm not sure what state you want to see the thread in. On most
systems today, once a thread has exit'ed, there's no way of
restarting it. And of course, a thread in a wait on a condition
takes 0 CPU time until someone wakes it up.

Hmmm... point taken. As I stated earlier - I have lots to learn :)

I'm afraid I don't see the difference. If someone starts a
thread when it's not wanted, you have a problem.

I was thinking that a condition is more bug-sensitive, than a
thread-restart() required. Of course thats human subjective impression
which doesn't mean much in a computer world :) Readjusted my views,
gonna have a look into the boost::condition.

Thanks for all your time! This will surely not be the last question you
hear from me *g*

Best Regards,

Lars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top