how a thread can signal when it's finished? - c++

#include <iostream>
#include <boost/thread.hpp>
using std::endl; using std::cout;
using namespace boost;
mutex running_mutex;
struct dostuff
{
volatile bool running;
dostuff() : running(true) {}
void operator()(int x)
{
cout << "dostuff beginning " << x << endl;
this_thread::sleep(posix_time::seconds(2));
cout << "dostuff is done doing stuff" << endl;
mutex::scoped_lock running_lock(running_mutex);
running = false;
}
};
bool is_running(dostuff& doer)
{
mutex::scoped_lock running_lock(running_mutex);
return doer.running;
}
int main()
{
cout << "Begin.." << endl;
dostuff doer;
thread t(doer, 4);
if (is_running(doer)) cout << "Cool, it's running.\n";
this_thread::sleep(posix_time::seconds(3));
if (!is_running(doer)) cout << "Cool, it's done now.\n";
else cout << "still running? why\n"; // This happens! :(
return 0;
}
Why is the output of the above program:
Begin..
Cool, it's running.
dostuff beginning 4
dostuff is done doing stuff
still running? why
How can dostuff correctly flag when it is done? I do not want to sit around waiting for it, I just want to be notified when it's done.

The problem in this example is that there are two instances of dostuff, so the version being set to false in operator() is different then the one in main.
From the thread management documentation:
A new thread is launched by passing an object of a callable type that can be invoked with no parameters to the constructor. The object is then copied into internal storage, and invoked on the newly-created thread of execution. If the object must not (or cannot) be copied, then boost::ref can be used to pass in a reference to the function object. In this case, the user of Boost.Thread must ensure that the referred-to object outlives the newly-created thread of execution.
If you don't want to copy the object, use boost::ref:
thread t(boost::ref(doer), 4);

You can't assume the thread will be finished just by sleeping.
You can call join on the thread. This will wait until the thread is done and then resume flow.
For advanced notifying between threads of a certain event happening you can use boost condition.

I'm guessing your problem is actually a bug in your code. From the Boost documentation for thread:
Thread Constructor with arguments
template <class F,class A1,class A2,...>
thread(F f,A1 a1,A2 a2,...);
Preconditions:
F and each An must by copyable or movable.
Effects:
As if thread(boost::bind(f,a1,a2,...)). Consequently, f and each an are copied into internal storage for access by the new thread.
So, I think the thread is modifying its own copy of doer, and not the object whose runnable state you're checking.

The real question isn't how the dostuff thread should send the signal, but rather how the main thread should receive the signal. My favorite method is to use socketpair() to create a local socket connection and then give one socket to the child thread and the other socket to the main thread. The two threads can then use the socket-connection to communicate with each other. In your case, all you would need is for the child thread to send a byte on the socket (or just close its socket file descriptor) just before it exits, and that would be enough to break the main thread out of select() or poll() or whatever it is blocking in and let it know that the child thread has finished its task.
Note that the main thread should still call join() on the child thread's thread-ID (after it receives the child-going-away signal), to make sure that the child thread is really really dead, before freeing any resources... otherwise you risk a race condition of the main thread freeing a resource after the child thread has signalled but before the thread-cleanup routines have completed.

Related

Relation between running Thread and the thread object

While learning basic thread management, I found difficulty in understanding these lines (in bold) from a book.
Once you’ve started your thread, you need to explicitly decide whether
to wait for it to finish (by joining with it—see section 2.1.2) or
leave it to run on its own (by detaching it—see section 2.1.3). If you
don’t decide before the std::thread object is destroyed, then your
program is terminated (the std::thread destructor calls
std::terminate()). It’s therefore imperative that you ensure that the
thread is correctly joined or detached, even in the presence of
exceptions. See section 2.1.3 for a technique to handle this scenario.
Note that you only have to make this decision before the std::thread
object is destroyed—the thread itself may well have finished long
before you join with it or detach it, and if you detach it, then the
thread may continue running long after the std::thread object is
destroyed.
When does a thread run even after the thread object is destroyed? Anyone have sample code or any reference?
What this means is that the lifetime of the thread is not associated with the lifetime of the thread object.
So the following code:
#include <thread>
#include <iostream>
int main() {
{ //scope the thread object
std::thread thr = std::thread([]() {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Thread stuff\r\n";
});
thr.detach();
} //thr is destroyed here
std::cout << "thr destroyed, start sleep\r\n";
std::this_thread::sleep_for(std::chrono::seconds(10));
std::cout << "sleep over\r\n";
}
Will output:
thr destroyed, start sleep
Thread stuff
sleep over

Why does this C++ thread code trigger an abort() error?

I am testing the new C++11 thread features. To do this, I start a thread by providing a lambda expression to its constructor:
int main()
{
thread t([]() {
cout << "Hello World!" << endl;
});
//this_thread::sleep_for(chrono::seconds(5));
cout << "I am done!" << endl;
getchar();
return 0;
}
But after I press a key (getchar), I get the error:
Can someone give a reason?
The behavior you're seeing is expected and the following explains how to avoid it.
From the std::thread::~thread documentation.
If *this has an associated thread (joinable() == true), std::terminate() is called.
A thread object does not have an associated thread (and is safe to destroy) after
it was default-constructed
it was moved from
join() has been called
detach() has been called
So what? I understand that join() must only be called for the main thread to wait for the worker thread. In this case, there is no purpose in waiting, because I press a key.
Why is there no purpose in waiting? What happens if the main function finishes execution before the std::cout stream object is used by the thread (albeit unlikely it's still possible even though you have the getchar() call)? Is that global stream object still valid for use by the thread?

When should I use std::thread::detach?

Sometime I have to use std::thread to speed up my application. I also know join() waits until a thread completes. This is easy to understand, but what's the difference between calling detach() and not calling it?
I thought that without detach(), the thread's method will work using a thread independently.
Not detaching:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called without detach");
});
//some code here
}
Calling with detaching:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called with detach");
});
t.detach();
//some code here
}
In the destructor of std::thread, std::terminate is called if:
the thread was not joined (with t.join())
and was not detached either (with t.detach())
Thus, you should always either join or detach a thread before the flows of execution reaches the destructor.
When a program terminates (ie, main returns) the remaining detached threads executing in the background are not waited upon; instead their execution is suspended and their thread-local objects destructed.
Crucially, this means that the stack of those threads is not unwound and thus some destructors are not executed. Depending on the actions those destructors were supposed to undertake, this might be as bad a situation as if the program had crashed or had been killed. Hopefully the OS will release the locks on files, etc... but you could have corrupted shared memory, half-written files, and the like.
So, should you use join or detach ?
Use join
Unless you need to have more flexibility AND are willing to provide a synchronization mechanism to wait for the thread completion on your own, in which case you may use detach
You should call detach if you're not going to wait for the thread to complete with join but the thread instead will just keep running until it's done and then terminate without having the spawner thread waiting for it specifically; e.g.
std::thread(func).detach(); // It's done when it's done
detach basically will release the resources needed to be able to implement join.
It is a fatal error if a thread object ends its life and neither join nor detach has been called; in this case terminate is invoked.
This answer is aimed at answering question in the title, rather than explaining the difference between join and detach. So when should std::thread::detach be used?
In properly maintained C++ code std::thread::detach should not be used at all. Programmer must ensure that all the created threads gracefully exit releasing all the acquired resources and performing other necessary cleanup actions. This implies that giving up ownership of threads by invoking detach is not an option and therefore join should be used in all scenarios.
However some applications rely on old and often not well designed and supported APIs that may contain indefinitely blocking functions. Moving invocations of these functions into a dedicated thread to avoid blocking other stuff is a common practice. There is no way to make such a thread to exit gracefully so use of join will just lead to primary thread blocking. That's a situation when using detach would be a less evil alternative to, say, allocating thread object with dynamic storage duration and then purposely leaking it.
#include <LegacyApi.hpp>
#include <thread>
auto LegacyApiThreadEntry(void)
{
auto result{NastyBlockingFunction()};
// do something...
}
int main()
{
::std::thread legacy_api_thread{&LegacyApiThreadEntry};
// do something...
legacy_api_thread.detach();
return 0;
}
When you detach thread it means that you don't have to join() it before exiting main().
Thread library will actually wait for each such thread below-main, but you should not care about it.
detach() is mainly useful when you have a task that has to be done in background, but you don't care about its execution. This is usually a case for some libraries. They may silently create a background worker thread and detach it so you won't even notice it.
According to cppreference.com:
Separates the thread of execution from the thread object, allowing
execution to continue independently. Any allocated resources will be
freed once the thread exits.
After calling detach *this no longer owns any thread.
For example:
std::thread my_thread([&](){XXXX});
my_thread.detach();
Notice the local variable: my_thread, while the lifetime of my_thread is over, the destructor of std::thread will be called, and std::terminate() will be called within the destructor.
But if you use detach(), you should not use my_thread anymore, even if the lifetime of my_thread is over, nothing will happen to the new thread.
Maybe it is good idea to iterate what was mentioned in one of the answers above: When the main function is finished and main thread is closing, all spawn threads either will be terminated or suspended. So, if you are relying on detach to have a background thread continue running after the main thread is shutdown, you are in for a surprise. To see the effect try the following. If you uncomment the last sleep call, then the output file will be created and written to fine. Otherwise not:
#include <mutex>
#include <thread>
#include <iostream>
#include <fstream>
#include <array>
#include <chrono>
using Ms = std::chrono::milliseconds;
std::once_flag oflag;
std::mutex mx;
std::mutex printMx;
int globalCount{};
std::ofstream *logfile;
void do_one_time_task() {
//printMx.lock();
//std::cout<<"I am in thread with thread id: "<< std::this_thread::get_id() << std::endl;
//printMx.unlock();
std::call_once(oflag, [&]() {
// std::cout << "Called once by thread: " << std::this_thread::get_id() << std::endl;
// std::cout<<"Initialized globalCount to 3\n";
globalCount = 3;
logfile = new std::ofstream("testlog.txt");
//logfile.open("testlog.txt");
});
std::this_thread::sleep_for(Ms(100));
// some more here
for(int i=0; i<10; ++i){
mx.lock();
++globalCount;
*logfile << "thread: "<< std::this_thread::get_id() <<", globalCount = " << globalCount << std::endl;
std::this_thread::sleep_for(Ms(50));
mx.unlock();
std::this_thread::sleep_for(Ms(2));
}
std::this_thread::sleep_for(Ms(2000));
std::call_once(oflag, [&]() {
//std::cout << "Called once by thread: " << std::this_thread::get_id() << std::endl;
//std::cout << "closing logfile:\n";
logfile->close();
});
}
int main()
{
std::array<std::thread, 5> thArray;
for (int i = 0; i < 5; ++i)
thArray[i] = std::thread(do_one_time_task);
for (int i = 0; i < 5; ++i)
thArray[i].detach();
//std::this_thread::sleep_for(Ms(5000));
std::cout << "Main: globalCount = " << globalCount << std::endl;
return 0;
}

Why might this thread management pattern result in a deadlock?

I'm using a common base class has_threads to manage any type that should be allowed to instantiate a boost::thread.
Instances of has_threads each own a set of threads (to support waitAll and interruptAll functions, which I do not include below), and should automatically invoke removeThread when a thread terminates to maintain this set's integrity.
In my program, I have just one of these. Threads are created on an interval every 10s, and each performs a database lookup. When the lookup is complete, the thread runs to completion and removeThread should be invoked; with a mutex set, the thread object is removed from internal tracking. I can see this working properly with the output ABC.
Once in a while, though, the mechanisms collide. removeThread is executed perhaps twice concurrently. What I can't figure out is why this results in a deadlock. All thread invocations from this point never output anything other than A. [It's worth noting that I'm using thread-safe stdlib, and that the issue remains when IOStreams are not used.] Stack traces indicate that the mutex is locking these threads, but why would the lock not be eventually released by the first thread for the second, then the second for the third, and so on?
Am I missing something fundamental about how scoped_lock works? Is there anything obvious here that I've missed that could lead to a deadlock, despite (or even due to?) the use of a mutex lock?
Sorry for the poor question, but as I'm sure you're aware it's nigh-on impossible to present real testcases for bugs like this.
class has_threads {
protected:
template <typename Callable>
void createThread(Callable f, bool allowSignals)
{
boost::mutex::scoped_lock l(threads_lock);
// Create and run thread
boost::shared_ptr<boost::thread> t(new boost::thread());
// Track thread
threads.insert(t);
// Run thread (do this after inserting the thread for tracking so that we're ready for the on-exit handler)
*t = boost::thread(&has_threads::runThread<Callable>, this, f, allowSignals);
}
private:
/**
* Entrypoint function for a thread.
* Sets up the on-end handler then invokes the user-provided worker function.
*/
template <typename Callable>
void runThread(Callable f, bool allowSignals)
{
boost::this_thread::at_thread_exit(
boost::bind(
&has_threads::releaseThread,
this,
boost::this_thread::get_id()
)
);
if (!allowSignals)
blockSignalsInThisThread();
try {
f();
}
catch (boost::thread_interrupted& e) {
// Yes, we should catch this exception!
// Letting it bubble over is _potentially_ dangerous:
// http://stackoverflow.com/questions/6375121
std::cout << "Thread " << boost::this_thread::get_id() << " interrupted (and ended)." << std::endl;
}
catch (std::exception& e) {
std::cout << "Exception caught from thread " << boost::this_thread::get_id() << ": " << e.what() << std::endl;
}
catch (...) {
std::cout << "Unknown exception caught from thread " << boost::this_thread::get_id() << std::endl;
}
}
void has_threads::releaseThread(boost::thread::id thread_id)
{
std::cout << "A";
boost::mutex::scoped_lock l(threads_lock);
std::cout << "B";
for (threads_t::iterator it = threads.begin(), end = threads.end(); it != end; ++it) {
if ((*it)->get_id() != thread_id)
continue;
threads.erase(it);
break;
}
std::cout << "C";
}
void blockSignalsInThisThread()
{
sigset_t signal_set;
sigemptyset(&signal_set);
sigaddset(&signal_set, SIGINT);
sigaddset(&signal_set, SIGTERM);
sigaddset(&signal_set, SIGHUP);
sigaddset(&signal_set, SIGPIPE); // http://www.unixguide.net/network/socketfaq/2.19.shtml
pthread_sigmask(SIG_BLOCK, &signal_set, NULL);
}
typedef std::set<boost::shared_ptr<boost::thread> > threads_t;
threads_t threads;
boost::mutex threads_lock;
};
struct some_component : has_threads {
some_component() {
// set a scheduler to invoke createThread(bind(&some_work, this)) every 10s
}
void some_work() {
// usually pretty quick, but I guess sometimes it could take >= 10s
}
};
Well, a deadlock might occurs if the same thread lock a mutex it has already locked (unless you use a recursive mutex).
If the release part is called a second time by the same thread as it seems to happen with your code, you have a deadlock.
I have not studied your code in details, but you probably have to re-design your code (simplify ?) to be sure that a lock can not be acquired twice by the same thread. You can probably use a safeguard checking for the ownership of the lock ...
EDIT:
As said in my comment and in IronMensan answer, one possible case is that the thread stop during creation, the at_exit being called before the release of the mutex locked in the creation part of your code.
EDIT2:
Well, with mutex and scoped lock, I can only imagine a recursive lock, or a lock that is not released. It can happen if a loop goes to infinite due to a memory corruption for instance.
I suggest to add more logs with a thread id to check if there is a recursive lock or something strange. Then I will check that my loop is correct. I will also check that the at_exit is only called once per thread ...
One more thing, check the effect of erasing (thus calling the destructor) of a thread while being in the at_exit function...
my 2 cents
You may need to do something like this:
void createThread(Callable f, bool allowSignals)
{
// Create and run thread
boost::shared_ptr<boost::thread> t(new boost::thread());
{
boost::mutex::scoped_lock l(threads_lock);
// Track thread
threads.insert(t);
}
//Do not hold threads_lock while starting the new thread in case
//it completes immediately
// Run thread (do this after inserting the thread for tracking so that we're ready for the on-exit handler)
*t = boost::thread(&has_threads::runThread<Callable>, this, f, allowSignals);
}
In other words, use thread_lock exclusively to protect threads.
Update:
To expand on something in the comments with speculation about how boost::thread works, the lock patterns could look something like this:
createThread:
(createThread) obtain threads_lock
(boost::thread::opeator =) obtain a boost::thread internal lock
(boost::thread::opeator =) release a boost::thread internal lock
(createThread) release threads_lock
thread end handler:
(at_thread_exit) obtain a boost::thread internal lock
(releaseThread) obtain threads_lock
(releaseThread) release threads_lock
(at_thread_exit) release a boost:thread internal lock
If those two boost::thread locks are the same lock, the potential for deadlock is clear. But this is speculation because much of the boost code scares me and I try not to look at it.
createThread could/should be reworked to move step 4 up between steps one and two and eliminate the potential deadlock.
It is possible that the created thread is finishing before or during the assignment operator in createThread is complete. Using an event queue or some other structure that is might be necessary. Though a simpler, though hack-ish, solution might work as well. Don't change createThread since you have to use threads_lock to protect threads itself and the thread objects it points to. Instead change runThread to this:
template <typename Callable>
void runThread(Callable f, bool allowSignals)
{
//SNIP setup
try {
f();
}
//SNIP catch blocks
//ensure that createThread is complete before this thread terminates
boost::mutex::scoped_lock l(threads_lock);
}

A way to destroy "thread" class

Here is a skeleton of my thread class:
class MyThread {
public:
virutal ~MyThread();
// will start thread with svc() as thread entry point
void start() = 0;
// derive class will specialize what the thread should do
virtual void svc() = 0;
};
Somewhere in code I create an instance of MyThread and later I want to destroy it.
In this case MyThread~MyThread() is called. MyThread:svc() is still running and using the object's data members. So I need a way politely inform MyThread:svc() to stop spinning, before proceeding with the destructor.
What is the acceptable way to destroy the thread object?
Note: I'm looking for platform agnostic solution.
UPD: It's clear that the root of problem is that there's no relationship between C++ object representing thread and OS thread. So the question is: in context of object destuction, is there an acceptable way to make thread object behave like an ordinary C++ object or should it be treated as an unusual one (e.g. should we call join() before destoying it?
Considering your additional requirements posted as comment to Checkers' reply (which is the
most straightforward way to do that):
I agree that join in DTor is problematic for various reasons. But from that the lifetime of your thread object is unrelated to the lifetime of the OS thread object.
First, you need to separate the data the thread uses from the thread object itself. They are distinct entities with distinct lifetime requirements.
One approach is to make the data refcounted, and have any thread that wants to access it hold a strong reference to the data. This way, no thread will suddenly grab into the void, but the data will be destroyed as soon as noone touches it anymore.
Second, about the thread object being destroyed when the thread joins:
I am not sure if this is a good idea. The thread object is normally a way to query the state of a thread - but with a thread object that dies as soon as the thread finishes, noone can tell you wether the thread finished.
Generally, I'd completely decouple the lifetime of the thread object from the lifetime of the OS thread: Destroying your thread object should not affect the thread itself. I see two basic approaches to this:
Thread Handle Object - reference counted again, returned by thread creator, can be released as early as one likes without affecting the OS thread. It would expose methods such as Join, IsFinished, and can give access to the thread shared data.
(If the thread object holds relevant execution state, the threafFunc itself could hold a reference to it, thereby ensuring the instance won't be released before the thread ends)
Thin Wrapper - You simply create a temporary around an OS thread handle. You could not hold additional state for the thread easily, but it might be just enough to make it work: At any place, you can turn an OS thread handle into an thread object. The majority of communication - e.g. telling the thread to terminate - would be via the shared data.
For your code example, this means: separate the start() from the svc()
You'd roughly work with this API (XxxxPtr could be e.g. boost::shared_ptr):
class Thread
{
public:
bool IsFinished();
void Join();
bool TryJoin(long timeout);
WorkerPtr GetWorker();
static ThreadPtr Start(WorkerPtr worker); // creates the thread
};
class Worker
{
private:
virtual void Svc() = 0;
friend class Thread; // so thread can run Svc()
}
Worker could contain a ThreadPtr itself, giving you a guarantee that the thread object exists during execution of Svc(). If multiple threads are allowed to work on the same data, this would have to be a thread list. Otherwise, Thread::Start would have to reject Workers that are already associated with a thread.
Motivation: What to do with rogue threads that block?
Assuming a thread fails to terminate within time for one reason or another, even though you told it to. You simply have three choices:
Deadlock, your applicaiton hangs. That usually happens if you join in the destructor.
Violently terminate the thread. That's potentially a violent termination of the app.
Let the thread run to completion on it's own data - you can notify the user, who can safely save & exit. Or you simply let the rogue thread dance on it's own copy of the data (not reference by the main thread anymore) until it completes.
Usually any OS-specific threads API will allow you to "join" a thread. That is, to block indefinitely on a thread handle until the thread functions returns.
So,
Signal the thread function to return (e.g. by setting a flag in its loop to false).
Join the thread, to make sure the actual thread terminates before you try to delete the thread object.
Then you can proceed with destruction of the thread object (you may also join in the destructor, though some people object to blocking destructors.).
I've had a project before with a similar "thread worker" class and a corresponding "work item" class (a-la Java's Thread and Runnable, except thread does not terminate but waits for a new Runnable object to be executed).
In the end, there was no difference if you join in a separate "shutdown" function or in the destructor, except a separate function is a bit more clear.
If you join in a destructor and a thread blocks, you will wait indefinitely.
If you join in a separate function and a thread blocks, you will wait indefinitely.
If you detach the thread and let it finish on its own, it will usually block application from exiting, so you will wait indefinitely.
So there is no straightforward way to make a thread behave like a regular C++ object and ignore its OS thread semantics, unless you can guarantee that your thread code can terminate almost immediately when notified to do so.
You could havee somthing like this in your svc method
while (alive){ //loops}
//free resources after while.
In your destructor, you could set the alive member to false. Or, you could have a pleaseDie() method, that sets the alive member to false, and can be called from the outside requesting the Thread instance to stop processing.
void
Thread::pleaseDie()
{
this->alive = false;
}
You first need a way to communicate with the thread to tell it to shut down. The best mechanism to do this depends on what svc() is doing. If, for example, it is looping on a message queue, you could insert a "please stop" message in that queue. Otherwise, you could simply add a member bool variable (and synchronize access to it) that is periodically checked by the svc(), and set by the thread wanting to destroy the object. Your could add a pure virtual stop() function to your base class, giving the implementor a clear signal that it has to implement svc() to make its class "runnable", and to implement stop() to make it "stoppable".
After asking the thread to stop, you must wait for it to exit before destroying the object. Again, there are several ways to do this. One is to make the stop() function blocking. It could wait, for example, for a "ok, I'm really stopped now" condition variable to be set by the thread running svc(). Alternatively, the caller could "wait" on the thread running svc(). The way to "wait" is platform dependent.
Most thread systems allow you to send a signal to a thead.
Example: pthreads
pthread_kill(pthread_t thread, int sig);
This will send a signall to a thread.
You can use this to kill the thread. Though this can leave a few of the resources hanging in an undefined state.
A solution to the resource problem is to install a signall handler.
So that when the signal handler is called it throws an exception. This will cause the thread stack to unwind to the entry point where you can then get the thread to check a variable about weather it is sill alive.
NOTE: You should never allow an exception to propogate out of a thread (this is so undefined my eyes bleed thinking about it). Basically catch the exception at the thread entry point then check some state variable to see if the thread should really exit.
Meanwhile the thread that sends the signal should wait for the thread to die by doing a join.
The only issues are that when you throw out of signal handler function you need to be careful. You should not use a signal that is asynchronus (ie one that could have been generated by a signal in another thread). A good one to use is SIGSEGV. If this happens normally then you have accessed invalid memory any you thread should think about exiting anyway!
You may also need to specify an extra flag on some systems to cope.
See This article
A working example using pthreads:
#include <pthread.h>
#include <iostream>
extern "C" void* startThread(void*);
extern "C" void shouldIexit(int sig);
class Thread
{
public:
Thread();
virtual ~Thread();
private:
friend void* startThread(void*);
void start();
virtual void run() = 0;
bool running;
pthread_t thread;
};
// I have seen a lot of implementations use a static class method to do this.
// DON'T. It is not portable. This is because the C++ ABI is not defined.
//
// It currently works on several compilers but will break if these compilers
// change the ABI they use. To gurantee this to work you should use a
// function that is declared as extern "C" this guarantees that the ABI is
// correct for the callback. (Note this is true for all C callback functions)
void* startThread(void* data)
{
Thread* thread = reinterpret_cast<Thread*>(data);
thread->start();
}
void shouldIexit(int sig)
{
// You should not use std::cout in signal handler.
// This is for Demo purposes only.
std::cout << "Signal" << std::endl;
signal(sig,shouldIexit);
// The default handler would kill the thread.
// But by returning you can continue your code where you left off.
// Or by throwing you can cause the stack to unwind (if the exception is caught).
// If you do not catch the exception it is implementation defined weather the
// stack is unwound.
throw int(3); // use int for simplicity in demo
}
Thread::Thread()
:running(true)
{
// Note starting the thread in the constructor means that the thread may
// start before the derived classes constructor finishes. This may potentially
// be a problem. It is started here to make the code succinct and the derived
// class used has no constructor so it does not matter.
if (pthread_create(&thread,NULL,startThread,this) != 0)
{
throw int(5); // use int for simplicity in demo.
}
}
Thread::~Thread()
{
void* ignore;
running = false;
pthread_kill(thread,SIGSEGV); // Tell thread it may want to exit.
pthread_join(thread,&ignore); // Wait for it to finish.
// Do NOT leave before thread has exited.
std::cout << "Thread Object Destroyed" << std::endl;
}
void Thread::start()
{
while(running)
{
try
{
this->run();
}
catch(...)
{}
}
std::cout << "Thread exiting" << std::endl;
}
class MyTestThread:public Thread
{
public:
virtual void run()
{
// Unless the signal causes an exception
// this loop will never exit.
while(true)
{
sleep(5);
}
}
};
struct Info
{
Info() {std::cout << "Info" << std::endl;}
~Info() {std::cout << "Done: The thread Should have exited before this" << std::endl;}
};
int main()
{
signal(SIGSEGV,shouldIexit);
Info info;
MyTestThread test;
sleep(4);
std::cout << "Exiting About to Exit" << std::endl;
}
> ./a.exe
Info
Exiting About to Exit
Signal
Thread exiting
Thread Object Destroyed
Done: The thread Should have exited before this
>
You should add dedicated thread management class (i.e. MyThreadMngr), that handles this and other tasks, like book keeping, owning the thread handles etc. The Thread itself should somehow signal to the thread manager that its going to terminate and MyThreadMngr should i.e. have a loop like Tom proposed.
There will probably be more actions that suite into such a thread manager class.
I reckon the easiest way to do this is to wrap the thread execution code in a loop
while(isRunning())
{
... thread implementation ...
}
You can also stop your thread by doing specific calls, for instance when you're using a WIN32 thread you can call TerminateThread on the thread handle in the destructor.
i give a simple and clean design, no signal, no sync, no kill needed.
per your MyThread, i suggest renaming and adding as below:
class MyThread {
public:
virutal ~MyThread();
// will be called when starting a thread,
// could do some initial operations
virtual bool OnStart() = 0;
// will be called when stopping a thread, say calling join().
virtual bool OnStop() = 0;
// derive class will specialize what the thread should do,
// say the thread loop such as
// while (bRunning) {
// do the job.
// }
virtual int OnRun() = 0;
};
the thread interface user will control the lifetime of MyThread.
and actually the real thread object is as below:
class IThread
{
public:
virtual API ~IThread() {}
/* The real destructor. */
virtual void Destroy(void) = 0;
/* Starts this thread, it will call MyThread::OnStart()
* and then call MyThread::OnRun() just after created
* the thread. */
virtual bool Start(void) = 0;
/* Stops a thread. will call MyThread::OnStop(). */
virtual void Stop(void) = 0;
/* If Wait() called, thread won't call MyThread::OnStop().
* If could, it returns the value of MyThread::OnRun()
* returned */
virtual int Wait(void) = 0;
/* your staff */
virtual MyThread * Command(void) = 0;
};
/* The interface to create a thread */
extern IThread * ThrdCreate(MyThread *p);
See the complete interfaces
http://effoaddon.googlecode.com/svn/trunk/devel/effo/codebase/addons/thrd/include/thrd_i.h
Coding Examples
Case 1. Controlled thread loop
class ThreadLoop : public MyThread
{
private:
bool m_bRunning;
public:
virtual bool OnStart() { m_bRunning = true; }
virtual bool OnStop() { m_bRunning = false; }
virtual int OnRun()
{
while (m_bRunning) {
do your job;
}
}
};
int main(int argc, char **argv)
{
ThreadLoop oLoop;
IThread *pThread = ThrdCreate(&oLoop);
// Start the thread, it will call Loop::OnStart()
//and then call Loop::OnRun() internally.
pThread->Start();
do your things here. when it is time to stop the thread, call stop().
// Stop the thread, it will call Loop::OnStop(),
// so Loop::OnRun() will go to the end
pThread->Stop();
// done, destroy the thread
pThread->Destroy();
}
Case 2. Don't know when the thread will stop
class ThreadLoop : public MyThread
{
public:
virtual bool OnStart() { }
virtual bool OnStop() { }
virtual int OnRun()
{
do your job until finish.
}
};
int main(int argc, char **argv)
{
ThreadLoop oLoop;
IThread *pThread = ThrdCreate(&oLoop);
// Start the thread, it will call Loop::OnStart()
//and then call Loop::OnRun() internally.
pThread->Start();
do your things here. Since you don't know when the job will
finish in the thread loop. call wait().
// Wait the thread, it doesn't call Loop::OnStop()
pThread->Wait();
// done, destroy the thread
pThread->Destroy();
}
A complete IThread implementation:
see
http://effoaddon.googlecode.com/svn/trunk/devel/effo/codebase/addons/thrd/src/thrd/thrd.cpp