multithreading thread switching issue - c++

I have a producer and consumer thread that are being created from main. They perform correctly well, except for the cout statement
class myclass{
int x;
// stuff
}
void foo1(myclass* ob){
setX(ob->x);
// stuff
}
void foo2(myclass* ob){
cout << ob->x << endl; // ONLY THIS DOESN'T EXECUTE
ob->getX();
// stuff
}
int main(){
myclass* ob = new myclass();
boost::thread producer_thread(boost::bind(foo1, ob));
boost::thread consumer_thread(boost::bind(foo2, ob));
// stuff
producer_thread.join();
consumer_thread.join();
}
Everything works fine (including showX that displays x, except for the cout. What's wrong?

Your threads are sharing the object without actually any lock on it. producer is not exiting before consumer started accessing the object.
Using producer_thread.join() before boost::thread consumer_thread(boost::bind(foo2, ob)) should resolve this, which is not the best fix. Using mutex locks will be ideal.

Adding to the previous answer, you can also use a state variable or condition variable to ensure that your object is not getting written upon / processed by a thread when some other thread is working on it. In other words, you can have a state variable whose value is changed by each function to a unique number upon completion and each function will start operating when the state variable is assumes the value that the previous function is supposed to set it to.

Related

How to initiate a thread in a class in C++ 14?

class ThreadOne {
public:
ThreadOne();
void RealThread();
void EnqueueJob(s_info job);
std::queue<s_info> q_jobs;
private:
H5::H5File* targetFile = new H5::H5File("file.h5", H5F_ACC_TRUNC);
std::condition_variable cv_condition;
std::mutex m_job_q_;
};
ThreadOne::ThreadOne() {
}
void ThreadOne::RealThread() {
while (true) {
std::unique_lock<std::mutex> lock(m_job_q_);
cv_condition.wait(lock, [this]() { return !this->q_jobs.empty(); });
s_info info = std::move(q_jobs.front());
q_jobs.pop();
lock.unlock();
//* DO THE JOB *//
}
}
void ThreadOne::EnqueueJob(s_info job) {
{
std::lock_guard<std::mutex> lock(m_job_q_);
q_jobs.push(std::move(job));
}
cv_condition.notify_one();
}
ThreadOne *tWrite = new ThreadOne();
I want to make a thread and send it a pointer of an array and its name as a struct(s_info), and then make the thread write it into a file. I think that it's better than creating a thread whenever writing is needed.
I could make a thread pool and allocate jobs to it, but it's not allowed to write the same file concurrently in my situation, I think that just making a thread will be enough and the program will still do CPU-bound jobs when writing job is in process.
To sum up, this class (hopefully) gets array pointers and their dataset names, puts them in q_jobs and RealThread writes the arrays into a file.
I referred to a C++ thread pool program and the program initiates threads like this:
std::vector<std::thread> vec_worker_threads;
vector_worker_threads.reserve(num_threads_);
vector_worker_threads.emplace_back([this]() { this->RealThread(); });
I'm new to C++ and I understand what the code above does, but I don't know how to initiate RealThread in my class without a vector. How can I make an instance of the class that has a thread(RealThread) that's already ready inside it?
From what I can gather, and as already discussed in the comments, you simply want a std::thread member for ThreadOne:
class ThreadOne {
std::thread thread;
public:
~ThreadOne();
//...
};
//...
ThreadOne::ThreadOne() {
thread = std::thread{RealThread, this};
}
ThreadOne::~ThreadOne() {
// (potentially) notify thread to finish first
if(thread.joinable())
thread.join();
}
//...
ThreadOne tWrite;
Note that I did not start the thread in the member-initializer-list of the constructor in order to avoid the thread accessing other members that have not been initialized yet. (The default constructor of std::thread does not start any thread.)
I also wrote a destructor which will wait for the thread to finish and join it. You must always join threads before destroying the std::thread object attached to it, otherwise your program will call std::terminate and abort.
Finally, I replaced tWrite from being a pointer to being a class type directly. There is probably no reason for you to use dynamic allocation there and even if you have a need for it, you should be using
auto tWrite = std::make_unique<ThreadOne>();
or equivalent, instead, so that you are not going to rely on manually deleteing the pointer at the correct place.
Also note that your current RealThread function seems to never finish. It must return at some point, probably after receiving a notification from the main thread, otherwise thread.join() will wait forever.

C++ Semaphore Confusion?

So, I'm writing a sort of oscilloscope-esque program that reads the the serial port on the computer and performs an fft on this data to convert it to the frequency spectrum. I ran into an issue though with the layout of my program which is broken up into a SerialHandler class (utilizing boost::Asio), an FFTHandler class, and a main function. The SerialHandler class uses the boost::Asio`` async_read_some function to read from the port and raise an event called HandleOnPortReceive which then reads the data itself.
The issue was that I couldn't find a way to pass that data from the event handler, being raised by an io_service object on another thread, to the FFTHandler class, which is on yet another thread. I was recommended to use semaphores to solve my problem, but I have next to no knowledge on semaphore.h usage, so my implementation is now rather broken and doesn't do much of anything it's supposed to.
Here's some code if that makes it a little clearer:
using namespace Foo;
//main function
int main(void){
SerialHandler serialHandler;
FFTHandler fftHandler;
sem_t *qSem_ptr = &qSem;
sem_init(qSem_ptr, 1, 0);
//create separate threads for both the io_service and the AppendIn so that neither will block the user input statement following
serialHandler.StartConnection(tempInt, tempString); //these args are defined, but for brevity's sake, I ommitted the declaration
t2= new boost::thread(boost::bind(&FFTHandler::AppendIn, &fftHandler, q, qSem));
//allow the user to stop the program and avoid the problem of an infinite loop blocking the program
char inChar = getchar();
if (inChar) {...some logic to stop reading}
}
namespace Foo{
boost::thread *t1;
boost::thread *t2;
sem_t qSem;
std::queue<double> q;
boost::mutex mutex_;
class SerialHandler{
private:
char *rawBuffer; //array to hold incoming data
boost::asio::io_service ioService;
boost::asio::serial_port_ptr serialPort;
public:
void SerialHandler::StartConnection(int _baudRate, string _comPort){
//some functionality to open the port that is irrelevant to the question goes here
AsyncReadSome(); //starts the read loop
//create thread for io_service object and let function go out of scope
t1 = new boost::thread(boost::bind(&boost::asio::io_service::run, &ioService));
}
void SerialHandler::AsyncReadSome(){
//there's some other stuff here for error_catching, but this is the only important part
serialPort->async_read_some (
boost::asio::buffer(rawBuffer, SERIAL_PORT_READ_BUF_SIZE),
boost::bind(
&SerialHandler::HandlePortOnReceive,
this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred, q));
}
void SerialHandler::HandlePortOnReceive(const boost::system::error_code& error, size_t bytes_transferred, std::queue<double>& q){
boost::mutex::scoped_lock lock(mutex_);
//more error checking goes here, but I've made sure they aren't returning and are not the issue
for (unsigned int i =0; i<bytes_transferred; i++){
unsigned char c = rawBuffer[i];
double d = (double) c; //loop through buffer and read
if (c==endOfLineChar){
} else //if not delimiting char, push into queue and post semaphore
{
q.push(d);
//cout << d << endl;
sem_post(&qSem);
cout << q.front() << endl;
cout << "size is: " << q.size() << endl;
}
}
//loop back on itself and start the next read
AsyncReadSome();
}
}
class FFTHandler{
private:
double *in; //array to hold inputs
fftw_complex *out; //holds outputs
int currentIndex;
bool filled;
const int N;
public:
void AppendIn(std::queue<double> &q, sem_t &qSem){
while(1){ //this is supposed to stop thread from exiting and going out of scope...it doesn't do that at all effectively...
cout << "test" << endl;
sem_wait(&_qSem); //wait for data...this is blocking but I don't know why
double d = _q.front();
_q.pop();
in[currentIndex]=d; //read queue, pop, then append in array
currentIndex++;
if (currentIndex == N){ //run FFT if full and reset index
currentIndex = N-overlap-1;
filled = true;
RunFFT();
}
}
}
}
}
That debug line in FFTHandler::AppendIn(..) is indeed firing, so the thread is being created, but it's immediateley going out of scope it seems and destructing the thread, because it seems I've set up the while to respond incorrectly to the semaphore.
TLDR: That was a long explanation to simply say, "I don't understand semaphores but need to somehow implement them. I tried, failed, so now I'm coming here to hopefully receive help on this code from somebody more knowledgeable than me.
UPDATE: So after playing around with some debug statements, it seems that the issue is that the while(1){...} statement is indeed firing, but, the sem_wait(&_qSem); is causing it to block. For whatever reason it is waiting indefinitely and despite the fact that the semaphore is being posted, it continues to wait and never progress beyond that line.
Since you're already using boost::mutex and its scoped lock type, I suggest you use boost::condition_variable instead of a POSIX semaphore. Otherwise you're mixing C++11-style synchronisation with POSIX synchronisation.
You lock the mutex when adding to the queue, but I don't see anything locking the mutex to read from the queue. It also looks like you're looping back to call AsyncReadSome while the mutex is still locked.
Pick a single form of synchronisation, and then use it correctly.
The initial value of the semaphore is 0 which is valid for this case. So it needs a sem_post for FFTHandler::AppendIn() to be unblocked. But I dont see the code that invokes SerialHandler::AsyncReadSome() for the first time for the serial port to be read and the push to happen into the queue. If you fix that part of the code, I think sem_post would happen and the FFTHandler thread would run. As the first step you can have debug prints one after the sem_wait and one inside AsyncReadSome() function, and my guess is that both wont get executed.
So, essentially you would want to ensure that 'reading' gets initiated and is kept alive as part of the main thread or a different thread.

Boost::thread how to get a pointer to the thread where my function is called?

With boost::thread how do I get a pointer to the boost::thread which is currently executing my function, from within that function?
The following does not compile for me:
boost::thread *currentThread = boost::this_thread;
You have to be careful because boost::thread is a movable type. Consider the following:
boost::thread
make_thread()
{
boost::thread thread([](boost::thread* p)
{
// here p points to the thread object we started from
}, &thread);
return thread;
}
// ...
boost::thread t = make_thread();
// if the thread is running by this point, p points to an non-existent object
A boost::thread object is conceptually associated to a thread but is not canonically associated to it, i.e. during the course of the thread more than one thread objects could have been associated with it (just not more than one at a given time). That's partly why boost::thread::id is here. So what is it you want to achieve exactly?
You can use boost::this_thread to reference the same thread you use it in.
See http://www.boost.org/doc/libs/1_41_0/doc/html/thread/thread_management.html
If you scour the Boost Thread documentation in its entirety (http://www.boost.org/doc/libs/release/doc/html/thread.html, or http://www.boost.org/doc/libs/1_60_0/doc/html/thread.html if that first link is broken), you'll find that there is no function provided to get a pointer to the boost::thread object that represents the current thread.
You can solve this problem on your own, however; one solution would be to use a map, mapping boost::thread:ids to boost:thread*s, and then access that map from within your thread to get the pointer.
For example:
#include <cstdio>
#include <map>
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
std::map<boost::thread::id, boost::thread*> threadsMap;
boost::mutex threadsMapMutex; // to synchronize access to the map
boost::mutex stdoutMutex; // to synchronize access to stdout
void thread_function()
{
threadsMapMutex.lock();
// get a pointer to this thread
boost::thread::id id = boost::this_thread::get_id();
boost::thread* thisThread = threadsMap.find(id)->second;
threadsMapMutex.unlock();
// do whatever it is that you need to do with the pointer
if(thisThread != NULL)
{
stdoutMutex.lock();
printf("I have a pointer to my own thread!\n");
stdoutMutex.unlock();
}
}
int main()
{
threadsMapMutex.lock();
// create the threads
boost::thread thread1(&thread_function);
boost::thread thread2(&thread_function);
// insert the threads into the map
threadsMap.insert(std::pair<boost::thread::id, boost::thread*>(thread1.get_id(), &thread1));
threadsMap.insert(std::pair<boost::thread::id, boost::thread*>(thread2.get_id(), &thread2));
threadsMapMutex.unlock();
// join the threads
thread1.join();
thread2.join();
return 0;
}
P.S. I just noticed that you posted in a comment that you're actually using this solution, after having already written this. Oh well--I still find it useful and complete to officially post the answer to your question, as well as (working) sample code for a potential solution.
Instead of using additional map, it is possible to bind the created thread pointer to thread function directly. As #luc-danton mentioned, you must be sure that given pointer is valid as long as thread is alive.
E.g, when using boost::thread_group, interanlly threads are stored as raw pointers in the list, so thread pointer is valid all time.
void thread_func(boost::shared_future<boost::thread*> thread_ptr_future)
{
// Do not continue until this thread pointer is not set.
boost::thread* this_thread_ptr = thread_ptr_future.get();
std::cout << "This thread pointer gained: " << this_thread_ptr << std::endl;
//... continue thread content with valid this thread pointer.
}
boost::thread_group m_threads; ///< Instead of manually creating the list of threads.
void start_new_thread()
{
boost::promise<boost::thread*> thr_promise;
boost::shared_future<boost::thread*> thr_future(thr_promise.get_future());
boost::thread* thread_ptr =
m_threads.create_thread(boost::bind(thread_func, thr_future));
thr_promise.set_value(thread_ptr);
}

how a thread can signal when it's finished?

#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.

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