|
Boost Users : |
From: James Zappia (James.Zappia_at_[hidden])
Date: 2002-12-05 12:56:00
> Thanks for all you help. I have a few new questions now, though. ;)
> Again, I'm a newbie to C++ so this may seem stupid...
>
> I created a boost::thread object and even though it goes out of scope,
> the thread continues to run.
>
>As it should, and as it's well documented. The boost::thread object is
>analogous to a std::fstream, where the file doesn't get deleted when the
>object goes out of scope. In other words, it's just a handle to the
>actual running thread.
Understood.
> Also, when passing a class with the
> operator() defined to boost::thread, it constructs and destructs the
> object several times which seems odd.
>
>Also well documented, and essential. If this didn't occur, you'd have to
>insure the lifetime of the object passed was longer than the lifetime of
>the thread of execution (not the boost::thread object, the actual thread
>of execution).
Understood.
> What I'm basically trying to do
> is run a thread, have that thread lock a timed_mutex, then do its job.
> Then, in main, I try to lock the same timed_mutex and if I can't get a
> lock before the time expires, I need to terminate the thread. Below is
> the source code and the output generated. My questions are below, after
> the output.
>
> SOURCE:
> #include <iostream>
> #include <boost/thread/xtime.hpp>
> #include <boost/thread/thread.hpp>
> #include <boost/thread/exceptions.hpp>
>
> using namespace std;
>
> boost::timed_mutex mutex;
>
> class thread_class
> {
> public:
> explicit thread_class(int sleep): _sleep(sleep) {};
>
> void operator()()
> {
> boost::xtime xt;
>
> cout << "thread: locking mutex\n";
> boost::timed_mutex::scoped_timed_lock lock(mutex,true);
>
>Why do you continue to use this syntax? This performs an explicit lock,
>not a timed lock. This overload is for two use cases:
>
>1) Creating an unlocked lock object:
>
>scoped_time_lock lock(mutex, false);
>
>2) Creating a locked lock object which later will be unlocked and then
>locked again through a timed lock:
>
>scoped_time_lock lock(mutex, true);
>// .. some code
>lock.unlock();
>// .. some code
>if (lock.timed_lock()) {
> // .. some code
>}
>
>Obviously the second use case will be extremely rare. In your case you're
>doing neither of these, and you'd be better served just using a simple
>scoped_lock.
>
> boost::xtime_get(&xt,boost::TIME_UTC);
>
> cout << "thread: sleeping for " << _sleep << " seconds\n";
>
> xt.sec += _sleep;
> boost::thread::sleep(xt);
>
> cout << "thread: freeing lock -- goodbye\n";
> }
>
> ~thread_class() { cout << "thread_class destructed\n"; }
>
> private:
> int _sleep;
> };
>
> int main( void )
> {
> {
> cout << "main: creating thread\n";
>
> thread_class test(10);
> boost::thread thrd(test);
>
> cout << "main: sleeping for 2 seconds\n";
> sleep(2);
>
> cout << "main: trying to lock mutex -- waiting 5
> seconds...\n";
>
> boost::timed_mutex::scoped_timed_lock lock(mutex,false);
>
> boost::xtime xt;
> boost::xtime_get(&xt,boost::TIME_UTC);
> xt.sec += 5;
>
> if ( lock.timed_lock(xt) )
> {
> cout << "obtain lock -- joining thread\n";
> thrd.join();
> }
> else
> {
> cout << "failed to obtain lock\n";
> }
> }
>
>I'd code this as:
>
>boost::xtime xt;
>boost::xtime_get(&xt, boost::TIME_UTC);
>xt.sec += 5;
>boost::timed_mutex::scoped_time_lock lock(mutex);
>if (lock) // or if (lock.locked())
>{
>// etc
I assume you mean boost::timed_mutex::scoped_timed_lock lock(mutex,xt)
because I don't see a constructor that takes only a timed_mutex. That
said, I agree that your way of doing it is better. Above you asked why I
continue to use the syntax I do for locking the mutex in the thread. I want
to immediately lock it, then in the main thread try to lock it for a finite
amount of time. I can't do that with scoped_lock. Perhaps my strategy is
wrong. I want to run a thread for only a specified amount of time. I can't
afford to block on a join() to wait for that thread to finish.
> cout << "main: making sure thread is gone\n";
>
>That's what join is for. I realize this is a toy example, but I can't see
>a valid reason for coding it this way. All you've done is introduce race
>conditions, even if they are conditions you can feel fairly confident will
>do what you want.
>
> sleep(10);
>
> return 0;
> }
>
> OUTPUT:
> main: creating thread
> thread_class destructed
> thread_class destructed
> thread_class destructed
> thread_class destructed
> main: sleeping for 2 seconds
> thread: locking mutex
> thread: sleeping for 10 seconds
> main: trying to lock mutex -- waiting 5 seconds...
> failed to obtain lock
> thread_class destructed
> main: making sure thread is gone
> thread: freeing lock -- goodbye
> thread_class destructed
>
> 1) Why are so many thread_class objects constructed/destructed when
> calling boost::thread?
>
>The number surprises me a little. I'd have expected two copies, knowing
>what I do about the implementation and with out carefully evaluating the
>code here. But the documentation is clear that the object will be copied
>AT LEAST once, and is free to copy the object any number of times. You
>need to account for this in your implementation if it matters.
Understood. Apologies for not thoroughly reading the doc first.
> 2) After the thread object (test) goes out of scope, why does the thread
> continue to run? Is it copied when calling boost::thread and run
> detached from the main thread?
>
>I don't know what you mean by "run detached from the main thread", but
>yes, test IS copied (but then, you know that based on what you asked in
>1). But then, maybe you meant something else. The "thread object" is
>actually "thrd" in your code above, not "test".
>
> 3) Is there a way I can cancel a thread if going out of scope doesn't
> stop it?
>
>Not yet, but there will be. However, I'm not sure that what you want to
>do is really to cancel the thread. It's hard to tell from this toy
>example.
What the application does is run a job (thread) that has a finite amount of
time to finish. If it doesn't finish in that time it needs to send an alert
and explicitly terminate the thread (because it can't be blocked with a
join() unless it knows the thread is done). As stated above, perhaps my
strategy of using the mutex to see if a thread ran in a given amount of time
is wrong.
Hopefully I'm making some sense, if not, I apologies.
James
>William E. Kempf
Info: <http://www.boost.org>
Wiki: <http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl>
Unsubscribe: <mailto:boost-users-unsubscribe_at_[hidden]>
Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
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