I made a multithread application that generates/destroy 100 threads continuously:
//Here is the thread class (one by every thread
struct s_control
{
data_in[D_BUFFER_SIZE];//data in to thread
data_out[D_BUFFER_SIZE];//data generated by the thread
//I use volatile in order to status data is avaiable in and out of the thread:
volatile __int16 status;//thread state 0=empty,1=full,2=filling (thread running)
}*control;
//Here is the thread main function
static void* F_pull(void* vv)//=pull_one_curl()
{
s_control* cc = (s_control* ) vv;
//use of cc->data_in and filling of cc->data out
cc->status=1; //Here advises that thread is finished and data out is filled
return NULL;
}
void main()
{
initialization();
control=new s_control[D_TAREAS];
pthread_t *tid=new pthread_t[D_TAREAS];
for (th=0;th<D_TAREAS;th++)
{ //Access to status of thread at the beginning
//(to avoid if it changes in the middle):
long status1=control[th].status
if (status1==0) //Thread finished and data_out of thread is empty
{ control[i2].status=2; //Filling in (thread initiated)status LLENANDO
error = pthread_create(&tid[th],NULL,F_pull,(void *) &control[th]);
}
else if (status1==1) //Thread finished and data_out of thread is full
{
//do things with control[th].data_out;
//and fill in control[th].data_in with data to pass to next thread
control[th].status=0; //Thread is finished and now its data_out is empty
}
else
{
//printf("\nThread#%li:filling",i2);
}
}while(!_kbhit());
finish();
}
Then as you can see, at the end of the thread, I used the variable volatile to advise that thread is about to exit:
begin of thread{ ....
cc->status=1; //Here advises that thread is finished and data out is filled
return NULL;
}//END OF THREAD
But after cc->status is set to 1 thread is not finished yet (it exist one more line)
So I do not like set status inside the thread.
I tried pthread_kill, but it didnĀ“t work, because it does not work until thread is alive, as can be seen at:
pthread_kill
I am not sure if this answers your question, but you can use pthread_join() to wait for a thread to terminate. In conjunction with some (properly synchronized) status variables, you should be able to achieve what you need.
Related
solved!: im copying the instance of Map in the new Thread an dont use the reference.
im learning how to use multiple threads. For this im programing a little game where i want the game to run in the main thread and the next chunk of the level shall be loaded in another thread. for this i set up a mutex around a vector to tell the loading thread what to load next. inside this mutex i also have a boolean to tell the thread when tu terminate.
initialising thread in Map::Map()
pending_orders_mutex = SDL_CreateMutex();
can_process_order = SDL_CreateCond();
chunk_loader_thread = SDL_CreateThread(Map::chunk_loader,"chunk_loader_thread",(void*)this);
loading thread
int Map::chunk_loader(void * data)
{
Map map = *(Map*)data;
bool kill_this_thread = false;
Chunk_Order actual_order;
actual_order.load_graphics = false;
actual_order.x = 0;
actual_order.y = 0;
while (!kill_this_thread)
{
SDL_LockMutex(map.pending_orders_mutex); // lock mutex
printf("3-kill_chunk_loader_thread: %d\n", map.kill_chunk_loader_thread);
kill_this_thread = map.kill_chunk_loader_thread;
printf("4-kill_chunk_loader_thread: %d\n", map.kill_chunk_loader_thread);
if (!kill_this_thread)
{
if (map.pending_orders.size())
{
actual_order = map.pending_orders.back();
map.pending_orders.pop_back();
printf("in thread processing order\n");
}
else
{
printf("in thread waiting for order\n");
SDL_CondWait(map.can_process_order, map.pending_orders_mutex);
}
}
SDL_UnlockMutex(map.pending_orders_mutex); // unlock mutex
//load actual order
}
printf("thread got killed\n");
return 0;
}
killing the thread (main thread)
SDL_LockMutex(pending_orders_mutex); // lock mutex
printf("setting kill command\n");
printf("1-kill_chunk_loader_thread: %d\n", kill_chunk_loader_thread);
kill_chunk_loader_thread = true; // send kill command
printf("2-kill_chunk_loader_thread: %d\n", kill_chunk_loader_thread);
SDL_CondSignal(can_process_order); // signal that order was pushed
SDL_UnlockMutex(pending_orders_mutex); // unlock mutex
SDL_WaitThread(chunk_loader_thread, NULL);
console output
3-kill_chunk_loader_thread: 0
4-kill_chunk_loader_thread: 0
in thread waiting for order
setting kill command
1-kill_chunk_loader_thread: 0
2-kill_chunk_loader_thread: 1
3-kill_chunk_loader_thread: 0
4-kill_chunk_loader_thread: 0
in thread waiting for order
why does the mainthread not change the "kill_chunk_loader_thread" boolean in the loading thread?
First of all, you should try to upload a minimal complete program in the question.
Its look like you set kill_chunk_loader_thread = true
but you didn't set map.kill_chunk_loader_thread = true
the section of map declaration is missig from your question, but I guess you didn't use a reference to the local or global variable, or you just perform struct copy so when you change one struct the other doesn't been affected at all.
EDIT:
Map map = *(Map*)data; copies the map structure (default copy constructor, I guess) so from now on if the source map change the copy won't.
You should keep work with the pointer, like this: Map* pMap = (Map*)data;
and check the pointer like this: kill_this_thread = pMap->kill_chunk_loader_thread; so you read from the source map.
This code is simplification of real project code. Main thread create worker thread and wait with std::condition_variable for worker thread really started. In code below std::condition_variable wakes up after current_thread_state becomes "ThreadState::Stopping" - this is the second notification from worker thread, that is the main thread did not wake up after the first notification, when current_thread_state becomes "ThreadState::Starting". The result was deadlock. Why this happens? Why std::condition_variable not wake up after first thread_event.notify_all()?
int main()
{
std::thread thread_var;
struct ThreadState {
enum Type { Stopped, Started, Stopping };
};
ThreadState::Type current_thread_state = ThreadState::Stopped;
std::mutex thread_mutex;
std::condition_variable thread_event;
while (true) {
{
std::unique_lock<std::mutex> lck(thread_mutex);
thread_var = std::move(std::thread([&]() {
{
std::unique_lock<std::mutex> lck(thread_mutex);
cout << "ThreadFunction() - step 1\n";
current_thread_state = ThreadState::Started;
}
thread_event.notify_all();
// This code need to disable output to console (simulate some work).
cout.setstate(std::ios::failbit);
cout << "ThreadFunction() - step 1 -> step 2\n";
cout.clear();
{
std::unique_lock<std::mutex> lck(thread_mutex);
cout << "ThreadFunction() - step 2\n";
current_thread_state = ThreadState::Stopping;
}
thread_event.notify_all();
}));
while (current_thread_state != ThreadState::Started) {
thread_event.wait(lck);
}
}
if (thread_var.joinable()) {
thread_var.join();
current_thread_state = ThreadState::Stopped;
}
}
return 0;
}
Once you call the notify_all method, your main thread and your worker thread (after doing its work) both try to get a lock on the thread_mutex mutex. If your work load is insignificant, like in your example, the worker thread is likely to get the lock before the main thread and sets the state back to ThreadState::Stopped before the main thread ever reads it. This results in a dead lock.
Try adding a significant work load, e.g.
std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
to the worker thread. Dead locks are far less likely now. Of course, this is not a fix for your problem. This is just for illustrating the problem.
You have two threads racing: one writes values of current_thread_state twice, another reads the value of current_thread_state once.
It is indeterminate whether the sequence of events is write-write-read or write-read-write as you expect, both are valid executions of your application.
So I have a thread that I was running using .join() but I needed an interactive user interface while running the thread so I stopped using join because it halted the program while it ran. The ui has a stop button to kill the thread and now I need a way to stop the thread without killing the whole program because I can't use .detach(). Thanks!
There is no safe way to unilaterally terminate a thread. Instead, the thread's code must periodically check whether the GUI thread has requested that it exit.
I'm not familiar with the new C++ library functions, but I believe you can do this with atomic_bool, e.g., see this question.
you could pass a reference to a bool variable to the thread and check if it is true. if it is, return from the thread.
Example:
bool terminate = false;
std::mutex m;
std::thread t([&terminate,&m] {
std::unique_lock<std::mutex> lm{m,std::defer_lock}; //don't lock yet
int i = 0;
while (true) {
lm.lock(); //protect terminate -> no race conditions
if (terminate)
return;
lm.unlock(); //release lock for terminate
//do what your thread should do
std::cout << i++ << std::endl;
}
});
/*
do something else here
*/
m.lock();
terminate = true;
m.unlock();
t.join();
Say the main thread created three worker threads.
Suppose all three threads run a function similar to work()
below.
bool signal[3]={false};
void* work(void* thread_id) //each worker thread is given a thread_id when created
{
int x = *(int*)thread_id;
int data;
/*code*/
signal[x] = true; //this thread finished
pthread_exit(&data);
}
Usually I use following code to join the threads.
int main()
{
pthread_t workerThreads[3];
int master;
/* code for creating threads */
for(int i=0;i<3;i++)
{
void* status;
master = pthread_join(workerThreads[i],&status);
/* code for handling the return data from thread*/
}
}
What I mean is if workerThreads[2] finished before workerThreads[0] , with the code above, main thread still have to wait for workerThreads[0] finish first before handling workerThreads[2]
Is there a way to join the threads without waiting?
Can I use something like this?
while(!signal[0]||!signal[1]||!signal[2]){
if(signal[0]){/*join workerThreads[0]*/}
if(signal[1]){/*join workerThreads[1]*/}
if(signal[2]){/*join workerThreads[2]*/}
}
I have a process that starts several threads which do some stuff, listen to some ports, etc.
After it starts all threads, the main thread currently goes into an infinite loop:
It's something like:
int main()
{
//start threads
while (true)
{
sleep(1000);
}
}
The extra sleep assures the main thread doesn't eat the processor.
Is this approach ok? Is there an industry standard on how a process is kept alivet? Thanks.
EDIT: Some clarifications:
the threads are listeners, so a join or WaitForSingleObject isn't an option. Usually I could use join here, but the threads are started by a third client library and I don't have any control over them.
doing some processing in the main thread doesn't make sense from a design point of view.
. Taken partially from the Linux Daemon Writing HOWTO, I assume you want something like this:
int main() {
pid_t pid;
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* If we got a good PID, then
we can exit the parent process. */
if (pid > 0) {
exit(EXIT_SUCCESS);
}
// now start threads & do the work
for( thread *t : threads ) {
join( t );
}
return 0;
}
This way the main process will exit, child process will spawn threads which will do the work. In the end the child process will wait for those threads to finish before exiting itself.
I'd suggest you to have your main thread waiting for the termination of the others:
int main( ) {
// start threads
for( thread *t : threads ) {
join( t );
}
// finalize everything or restart the thread
return 0;
}
If you're using POSIX threads, the pthread_join function will do this.
I don't believe that there is an industry standard.
What you have is a perfectly acceptable way of running the main thread. However you may want to include a way to break out of the loop.
Other methods include:
Waiting for all the worker threads to complete using a join command.
Waiting on an event in the the main thread which can be signalled to exit the loop.
Using the main thread to do some of the processing currently done by a worker thread.
Periodically checking a boolean flag to decide whether to exit or not.
At the end of the day, it depends on your specific requirements.