How to suspend and resume a POSIX thread in C++? - c++

As I came to know creating and terminating thread abruptly
using pthread_kill() everytime is not a good way to do, so I am going
with suspend and resume method for a thread using thread1.suspend() and
thread1.resume(), whenever needed. How to do/implement this?
Take below LED blinking code for reference. During thread1.start() creating thread with suspended = false; is continuing as it is stuck in a while loop.
Calling thread1.suspend() has no effect.
#define on 1
#define off 0
void gpio_write(int fd, int value);
void* led_Flash(void* args);
class PThread {
public:
pthread_t threadID;
bool suspended;
int fd;
pthread_mutex_t m_SuspendMutex;
pthread_cond_t m_ResumeCond;
void start() {
suspended = false;
pthread_create(&threadID, NULL, led_Flash, (void*)this );
}
PThread(int fd1) { this->fd=fd1; }
~PThread() { }
void suspend() {
pthread_mutex_lock(&m_SuspendMutex);
suspended = true;
printf("suspended\n");
do {
pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
} while (suspended);
pthread_mutex_unlock(&m_SuspendMutex);
}
void resume() {
/* The shared state 'suspended' must be updated with the mutex held. */
pthread_mutex_lock(&m_SuspendMutex);
suspended = false;
printf("Resumed\n");
pthread_cond_signal(&m_ResumeCond);
pthread_mutex_unlock(&m_SuspendMutex);
}
};
void* led_Flash(void* args)
{
PThread* pt= (PThread*) args;
int ret=0;
int fd= pt->fd;
while(pt->suspended == false)
{
gpio_write(fd,on);
usleep(1);
gpio_write(fd,off);
usleep(1);
}
return NULL;
}
int main()
{
int fd1=1,fd2=2, fd3=3;
class PThread redLED(fd1);
class PThread amberLED(fd2);
class PThread greenLED(fd3);
redLED.start();
amberLED.start();
greenLED.start();
sleep(1);
redLED.suspend();
return 0;
}
Could some body help me, please?

After a little modification of above code , it seems working . Thanks guy for pointing out issues on above code, the changes are as follow.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<iostream>
#define on 1
#define off 0
void gpio_write(int fd, int value);
void* led_Flash(void* args);
class PThread {
public:
pthread_t threadID;
volatile int suspended;
int fd;
pthread_mutex_t lock;
PThread(int fd1)
{
this->fd=fd1;
this->suspended =1; //Initial state: suspend blinking untill resume call
pthread_mutex_init(&this->lock,NULL);
pthread_create(&this->threadID, NULL, led_Flash, (void*)this );
}
~PThread()
{
pthread_join(this->threadID , NULL);
pthread_mutex_destroy(&this->lock);
}
void suspendBlink() {
pthread_mutex_lock(&this->lock);
this->suspended = 1;
pthread_mutex_unlock(&this->lock);
}
void resumeBlink() {
pthread_mutex_lock(&this->lock);
this->suspended = 0;
pthread_mutex_unlock(&this->lock);
}
};
void gpio_write(int fd, int value)
{
if(value!=0)
printf("%d: on\n", fd);
else
printf("%d: off\n", fd);
}
void* led_Flash(void* args)
{
PThread* pt= (PThread*) args;
int fd= pt->fd;
while(1)
{
if(!(pt->suspended))
{
gpio_write(fd,on);
usleep(1);
gpio_write(fd,off);
usleep(1);
}
}
return NULL;
}
int main()
{
//Create threads with Initial state: suspend/stop blinking untill resume call
class PThread redLED(1);
class PThread amberLED(2);
class PThread greenLED(3);
// Start blinking
redLED.resumeBlink();
amberLED.resumeBlink();
greenLED.resumeBlink();
sleep(5);
// suspend/stop blinking
amberLED.suspendBlink();
sleep(5);
redLED.suspendBlink();
sleep(5);
amberLED.suspendBlink();
sleep(5);
redLED.resumeBlink();
pthread_exit(NULL);
return 0;
}

Related

How to fix the next thread to be more correct? Using Pthread

I'm investigating the use of PThread.
The main process opens the camera and gets a matrix. Then calls the thread that running job in robot and I want it to be parallel. Basically it works and runs. But still feel unprofessional- because of the bool.
In the code below, this is an example (with fprintf).
I'd love to know how I can fix it without harm parallelism.
In the next code I do not show the call to the robot or camera opening.
There is a feeling that a mutex is needed.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <opencv2/opencv.hpp>
#include <unistd.h> /// for sleep
bool inThread = false;
void *print_message_function( void *ptr );
int main()
{
char mkey = 0;
pthread_t thread1;
char *message1 = "Thread 1";
int iret1;
cv::Mat bgr_image = imread("image.bmp",cv::IMREAD_COLOR);
while(mkey!=27){
if(!inThread){
inThread = true;
iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
}
printf("In Main");
imshow("mat", bgr_image);
mkey = cv:: waitKey(5);
}
return 0;
}
void *print_message_function( void *ptr )
{
char *message;
message = (char *) ptr;
printf("%s \n", message);
sleep(2);
inThread = false;
pthread_exit(NULL);
}
The code works great and does not fall, but it seems unprofessional. Is there a chance that when you update the flag, it will check what is in the flag and fall?
inThread is concurrently read/written so its access shall be protected.
Using a mutex this can for example be done like follows.
Define a global mutex and initialise it:
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
Include errno to be able to do convenient error checking/logging for the pthread_*() calls:
#include <errno.h>
Change this
if(!inThread){
inThread = true;
iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
}
to become
errno = pthread_mutex_lock(&m);
if (errno) {
perror("pthread_mutex_lock() failed");
exit(EXIT_FAILURE);
}
if (!inThread) {
inThread = true;
errno = pthread_mutex_unlock(&m);
if (errno) {
perror("pthread_mutex_unlock() failed");
exit(EXIT_FAILURE);
}
...
}
else {
errno = pthread_mutex_unlock(&m);
if (errno) {
perror("pthread_mutex_unlock() failed");
exit(EXIT_FAILURE);
}
}
And change this
inThread = false;
to become
errno = pthread_mutex_lock(&m);
if (errno) {
perror("pthread_mutex_lock() failed");
exit(EXIT_FAILURE);
}
inThread = false;
errno = pthread_mutex_unlock(&m);
if (errno) {
perror("pthread_mutex_unlock() failed");
exit(EXIT_FAILURE);
}

Assertion failed on __pthread_mutex_cond_lock_full in a load test

I used the following code to create a timer object in my c++ application running on a debian 8.
class Timer
{
private:
std::condition_variable cond_;
std::mutex mutex_;
int duration;
void *params;
public:
Timer::Timer(void (*func)(void*))
{
this->handler = func;
this->duration = 0;
this->params = NULL;
};
Timer::~Timer(){};
void Timer::start(int duree, void* handlerParams)
{
this->duration = duree;
this->params = handlerParams;
/*
* Launch the timer thread and wait it
*/
std::thread([this]{
std::unique_lock<std::mutex> mlock(mutex_);
std::cv_status ret = cond_.wait_for(mlock,
std::chrono::seconds(duration));
if ( ret == std::cv_status::timeout )
{
handler(params);
}
}).detach();
};
void Timer::stop()
{
cond_.notify_all();
}
};
It works correctly under gdb and under normal conditions, but in a load test of 30 requests or more, it crashes with the assertion :
nptl/pthread_mutex_lock.c:350: __pthread_mutex_cond_lock_full: Assertion `(-(e)) != 3 || !robust' failed.
I don't understand the cause of this assertion. Can anyone help me please ??
Thank you
Basically you have a detached thread that accesses the timer object, so it's likely that you destroyed the Timer object but the thread is still running and accessing it's member(mutex, conditional variable).
The assert itself says, from glibc source code, that the owner of the mutex has died.
Thanks a lot for your comments ! I'll try to change the thread detach, and do the load tests.
This is a MVCE of my problem, which is a part of a huge application.
/**
* \file Timer.hxx
* \brief Definition of Timer class.
*/
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>
class Timer
{
private:
std::condition_variable cond_;
std::mutex mutex_;
int duration;
void *params;
public:
Timer(void (*func)(void*));
~Timer();
void (*handler)(void*);
void start(int duree, void* handlerParams);
void stop();
};
/*
* Timer.cxx
*/
#include "Timer.hxx"
Timer::Timer(void (*func)(void*))
{
//this->set_handler(func, params);
this->handler = func;
this->duration = 0;
this->params = NULL;
}
Timer::~Timer()
{
}
void Timer::start(int duree, void* handlerParams)
{
this->duration = duree;
this->params = handlerParams;
/*
* Launch the timer thread and wait it
*/
std::thread([this]{
std::unique_lock<std::mutex> mlock(mutex_);
std::cv_status ret = cond_.wait_for(mlock, std::chrono::seconds(duration));
if ( ret == std::cv_status::timeout )
{
handler(params);
}
}).detach();
}
void Timer::stop()
{
cond_.notify_all();
}
/*
* MAIN
*/
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include "Timer.hxx"
using namespace std;
void timeoutHandler(void* params)
{
char* data= (char*)params;
cout << "Timeout triggered !! Received data is: " ;
if (data!=NULL)
cout << data << endl;
}
int main(int argc, char **argv)
{
int delay=5;
char data[20] ="This is a test" ;
Timer *t= new Timer(&timeoutHandler) ;
t->start(delay, data);
cout << "Timer started !! " << endl;
sleep(1000);
t->stop();
delete t;
cout << "Timer deleted !! " << endl;
return 0;
}

pthread_create Error in Visual Studio

Hi I'm using Visual Studio 2010 and having trouble getting this barber shop program to work.
I get this error
pthread_create : cannot convert parameter 3 from void *(__cdecl *)(void) to void *(__cdecl *)(void *)
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <Windows.h>
#define seats 6
void *customerMaker();
void *barberShop();
void *waitingRoom();
void checkQueue();
pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t wait_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t sleep_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t barberSleep_cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t barberWorking_cond = PTHREAD_COND_INITIALIZER;
int returnTime=5,current=0, sleeping=0, iseed;
int main(int argc, char *argv[])
{
iseed=time(NULL);
srand(iseed);
//declare barber thread;
pthread_t barber,customerM,timer_thread;
pthread_attr_t barberAttr, timerAttr;
pthread_attr_t customerMAttr;
//define barber, and cutomerMaker default attributes
pthread_attr_init(&timerAttr);
pthread_attr_init(&barberAttr);
pthread_attr_init(&customerMAttr);
printf("\n");
//create cutomerMaker
pthread_create(&customerM,&customerMAttr,customerMaker,NULL);
//create barber
pthread_create(&barber,&barberAttr,barberShop,NULL);
pthread_join(barber,NULL);
pthread_join(customerM,NULL);
return 0;
}
void *customerMaker()
{
int i=0;
printf("*Customer Maker Created*\n\n");
fflush(stdout);
pthread_t customer[seats+1];
pthread_attr_t customerAttr[seats+1];
while(i<(seats+1))
{
i++;
pthread_attr_init(&customerAttr[i]);
while(rand()%2!=1)
{
Sleep(1);
}
pthread_create(&customer[i],&customerAttr[i],waitingRoom,NULL);
}
pthread_exit(0);
}
void *waitingRoom()
{
//take seat
pthread_mutex_lock(&queue_mutex);
checkQueue();
Sleep(returnTime);
waitingRoom();
}
void *barberShop()
{
int loop=0;
printf("The barber has opened the store.\n");
fflush(stdout);
while(loop==0)
{
if(current==0)
{
printf("\tThe shop is empty, barber is sleeping.\n");
fflush(stdout);
pthread_mutex_lock(&sleep_mutex);
sleeping=1;
pthread_cond_wait(&barberSleep_cond,&sleep_mutex);
sleeping=0;
pthread_mutex_unlock(&sleep_mutex);
printf("\t\t\t\tBarber wakes up.\n");
fflush(stdout);
}
else
{
printf("\t\t\tBarber begins cutting hair.\n");
fflush(stdout);
Sleep((rand()%20)/5);
current--;
printf("\t\t\t\tHair cut complete, customer leaving store.\n");
pthread_cond_signal(&barberWorking_cond);
}
}
pthread_exit(0);
}
void checkQueue()
{
current++;
printf("\tCustomer has arrived in the waiting room.\t\t\t\t\t\t\t%d Customers in store.\n",current);
fflush(stdout);
printf("\t\tCustomer checking chairs.\n");
fflush(stdout);
if(current<seats)
{
if(sleeping==1)
{
printf("\t\t\tBarber is sleeping, customer wakes him.\n");
fflush(stdout);
pthread_cond_signal(&barberSleep_cond);
}
printf("\t\tCustomer takes a seat.\n");
fflush(stdout);
pthread_mutex_unlock(&queue_mutex);
pthread_mutex_lock(&wait_mutex);
pthread_cond_wait(&barberWorking_cond,&wait_mutex);
pthread_mutex_unlock(&wait_mutex);
return;
}
if(current>=seats)
{
printf("\t\tAll chairs full, leaving store.\n");
fflush(stdout);
current--;
pthread_mutex_unlock(&queue_mutex);
return;
}
}
waitingRoom must accept a pointer parameter. See the pthread_create documentation.

Make thread loop for 5 iterations; pthreads, mutex, and semaphors

I have this code in an example for my class, and the instructions from the teacher say to "make each thread loop for 5 iterations". I am confused as to how to do that, wtih this code:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <sys/utsname.h>
/* Symbolic Constants*/
#define NUM_THREADS 4
#define BUFFER_SIZE 10
/* Semaphore and Mutex lock */
sem_t cEmpty;
sem_t cFull;
pthread_mutex_t mutex;
/* Threads */
pthread_t tid; /* Thread ID */
pthread_attr_t attr; /* Thread attributes */
//prototypes
void *producer(void *param);
void *consumer(void *param);
int insert_item(int threadID);
int remove_item(int threadID);
void init();
/* Progress Counter and Thread IDs*/
int counter, pthreadID=0, cthreadID=0;
int main()
{
/* Variables */
int c1;
/* Perform initialization */
init();
/* Create the producer threads */
for(c1=0; c1<NUM_THREADS; c1++)
{
pthread_create(&tid, &attr, producer, NULL);
}
/* Create the consumer threads */
for(c1=0; c1<NUM_THREADS; c1++)
{
pthread_create(&tid, &attr, consumer, NULL);
}
/* Ending it */
sleep(2);
printf("All threads are done.\n");
/* Destroy the mutex and semaphors */
pthread_mutex_destroy(&mutex);
sem_destroy(&cEmpty);
sem_destroy(&cFull);
printf("Resources cleaned up.\n");
exit(0);
}
void init()
{
pthread_mutex_init(&mutex, NULL); /* Initialize mutex lock */
pthread_attr_init(&attr); /* Initialize pthread attributes to default */
sem_init(&cFull, 0, 0); /* Initialize full semaphore */
sem_init(&cEmpty, 0, BUFFER_SIZE); /* Initialize empty semaphore */
counter = 0; /* Initialize global counter */
}
void *producer(void *param)
{
int x;
for(x=0; x<5;)
{
sleep(1);
sem_wait(&cEmpty); /* Lock empty semaphore if not zero */
pthread_mutex_lock(&mutex);
if(insert_item(pthreadID))
{
fprintf(stderr, "Producer error.");
}
else
{
pthreadID++;
x++;
}
pthread_mutex_unlock(&mutex);
sem_post(&cFull); /* Increment semaphore for # of full */
}
return 0;
}
void *consumer(void *param)
{
int y;
for(y=0; y<5;)
{
sleep(1);
sem_wait(&cFull); /* Lock empty semaphore if not zero */
pthread_mutex_lock(&mutex);
if(remove_item(cthreadID))
{
fprintf(stderr, "Consumer error.");
}
else
{
cthreadID++;
y++;
}
pthread_mutex_unlock(&mutex);
sem_post(&cEmpty); /* Increments semaphore for # of empty */
}
return 0;
}
int insert_item(int threadID)
{
if(counter < BUFFER_SIZE) /* Buffer has space */
{
counter++;
printf("Producer %d inserted a cookie. Total:%d\n", threadID, counter);
return 0;
}
else /* Buffer full */
{
return -1;
}
}
int remove_item(int threadID)
{
if(counter > 0) /* Buffer has something in it */
{
counter--;
printf("Consumer %d removed a cookie. Total:%d\n", threadID, counter);
return 0;
}
else /* Buffer empty */
{
return -1;
}
}
Anyone have any idea of where I add my for loop to "make each thread loop for 5 iterations"? Thank you so much in advanced.
UPDATE: I changed the while(1) to a for loop with 5 iterations, but I still cant get the messages from the insert_item and remove_item functions to print 5 times, the only print once. Anyone know how I can get it to print 5 times?
The problem was that at the end of main, I call sleep(2). This is not enough time for all of the threads to print their output. I was also not passing the right index to my add_item and remove_item functions. In addition, I needed a join command for all of the threads rather than the sleep command, and the join command ensures that all of the threads finish before the program exits. Here is the updated and corrected code. Hope this helps someone trying to do something similar!
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <sys/utsname.h>
// Symbolic Constants
#define NUM_THREADS 4
#define BUFFER_SIZE 10
// Semaphore and Mutex lock
sem_t cEmpty;
sem_t cFull;
pthread_mutex_t mutex;
// Threads
pthread_t tid[NUM_THREADS]; //Thread ID
pthread_t tid2[NUM_THREADS]; //Thread ID
pthread_attr_t attr; //Thread attributes
//prototypes
void *producer(void *param);
void *consumer(void *param);
int insert_item(long threadID);
int remove_item(long threadID);
void init();
//Progress Counter and Thread IDs
int counter=0;
int main()
{
//Variables
long c1;
//Perform initialization
init();
//Create the producer threads
for(c1=0; c1<NUM_THREADS; c1++)
{
pthread_create(&tid[c1], &attr, producer, (void *)c1);
pthread_create(&tid2[c1], &attr, consumer, (void *)c1);
}
//Ending it
for(c1=0; c1<NUM_THREADS; c1++)
{
pthread_join(tid[c1], NULL);
pthread_join(tid2[c1],NULL);
}
printf("All threads are done.\n");
//Destroy the mutex and semaphors
pthread_mutex_destroy(&mutex);
sem_destroy(&cEmpty);
sem_destroy(&cFull);
printf("Resources cleaned up.\n");
exit(0);
}
//This function performs initialization
void init()
{
pthread_mutex_init(&mutex, NULL); //Initialize mutex lock
pthread_attr_init(&attr); //Initialize pthread attributes to default
sem_init(&cFull, 0, 0); //Initialize full semaphore
sem_init(&cEmpty, 0, BUFFER_SIZE); //Initialize empty semaphore
counter = 0; //Initialize global counter
}
//This function creates the producer thread
void *producer(void *param)
{
long index = (long)param;
for(int x = 0; x<5; x++)
{
sleep(1);
sem_wait(&cEmpty); //Lock empty semaphore if not zero
pthread_mutex_lock(&mutex);
//check to see if item inserted correctly; print error on fail
if(insert_item(index))
{
fprintf(stderr, "Producer error.");
}
pthread_mutex_unlock(&mutex);
sem_post(&cFull); //Increment semaphore for # of full
}
pthread_exit(NULL);
return 0;
}
//This function created the consumer thread
void *consumer(void *param)
{
long index = (long)param;
for(int x = 0; x<5; x++)
{
sleep(1);
sem_wait(&cFull); //Lock empty semaphore if not zero
pthread_mutex_lock(&mutex);
//print error if cookie not decremented correctly
if(remove_item(index))
{
fprintf(stderr, "Consumer error.");
}
pthread_mutex_unlock(&mutex);
sem_post(&cEmpty); //Increments semaphore for # of empty
}
pthread_exit(NULL);
return 0;
}
//Insert item function to increment the cookie count and print thread message
int insert_item(long threadID)
{
if(counter < BUFFER_SIZE) //Buffer has space
{
counter++;
printf("Producer %ld inserted a cookie. Total:%d\n", threadID, counter);
return 0;
}
else //Buffer full
{
return -1;
}
}
//Remove item function to decrement the cookie count and print thread message
int remove_item(long threadID)
{
if(counter > 0) //Buffer has something in it
{
counter--;
printf("Consumer %ld removed a cookie. Total:%d\n", threadID, counter);
return 0;
}
else //Buffer empty
{
return -1;
}
}

Embedding matplotlib in C++

I am reading a message from a socket with C++ code and am trying to plot it interactively with matplotlib, but it seems Python code will block the main thread, no matter I use show() or ion() and draw(). ion() and draw() won't block in Python.
Any idea how to plot interactively with matplotlib in C++ code?
An example would be really good.
Thanks a lot.
You may also try creating a new thread that does the call to the
blocking function, so that it does not block IO in your main program
loop. Use an array of thread objects and loop through to find an unused
one, create a thread to do the blocking calls, and have another thread
that joins them when they are completed.
This code is a quick slap-together I did to demonstrate what I mean about
using threads to get pseudo asynchronous behavior for blocking functions...
I have not compiled it or combed over it very well, it is simply to show
you how to accomplish this.
#include <pthread.h>
#include <sys/types.h>
#include <string>
#include <memory.h>
#include <malloc.h>
#define MAX_THREADS 256 // Make this as low as possible!
using namespace std;
pthread_t PTHREAD_NULL;
typedef string someTypeOrStruct;
class MyClass
{
typedef struct
{
int id;
MyClass *obj;
someTypeOrStruct input;
} thread_data;
void draw(); //Undefined in this example
bool getInput(someTypeOrStruct *); //Undefined in this example
int AsyncDraw(MyClass * obj, someTypeOrStruct &input);
static void * Joiner(MyClass * obj);
static void * DoDraw(thread_data *arg);
pthread_t thread[MAX_THREADS], JoinThread;
bool threadRunning[MAX_THREADS], StopJoinThread;
bool exitRequested;
public:
void Main();
};
bool MyClass::getInput(someTypeOrStruct *input)
{
}
void MyClass::Main()
{
exitRequested = false;
pthread_create( &JoinThread, NULL, (void *(*)(void *))MyClass::Joiner, this);
while(!exitRequested)
{
someTypeOrStruct tmpinput;
if(getInput(&tmpinput))
AsyncDraw(this, tmpinput);
}
if(JoinThread != PTHREAD_NULL)
{
StopJoinThread = true;
pthread_join(JoinThread, NULL);
}
}
void *MyClass::DoDraw(thread_data *arg)
{
if(arg == NULL) return NULL;
thread_data *data = (thread_data *) arg;
data->obj->threadRunning[data->id] = true;
// -> Do your draw here <- //
free(arg);
data->obj->threadRunning[data->id] = false; // Let the joinThread know we are done with this handle...
}
int MyClass::AsyncDraw(MyClass *obj, someTypeOrStruct &input)
{
int timeout = 10; // Adjust higher to make it try harder...
while(timeout)
{
for(int i = 0; i < MAX_THREADS; i++)
{
if(thread[i] == PTHREAD_NULL)
{
thread_data *data = (thread_data *)malloc(sizeof(thread_data));
if(data)
{
data->id = i;
data->obj = this;
data->input = input;
pthread_create( &(thread[i]), NULL,(void* (*)(void*))MyClass::DoDraw, (void *)&data);
return 1;
}
return 0;
}
}
timeout--;
}
}
void *MyClass::Joiner(MyClass * obj)
{
obj->StopJoinThread = false;
while(!obj->StopJoinThread)
{
for(int i = 0; i < MAX_THREADS; i++)
if(!obj->threadRunning[i] && obj->thread[i] != PTHREAD_NULL)
{
pthread_join(obj->thread[i], NULL);
obj->thread[i] = PTHREAD_NULL;
}
}
}
int main(int argc, char **argv)
{
MyClass base;
base.Main();
return 0;
}
This way you can continue accepting input while the draw is occurring.
~~Fixed so the above code actually compiles, make sure to add -lpthread