How to destroy threads in C#?
Answers
(Thread creation and Identification) of the Linux Thread series, we discussed about thread IDs, how to compare two thread IDs and how to create a thread.
C Thread Example Program
If we take the same example as discussed in part-II of this series :
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
pthread_t tid[2];
void* doSomeThing(void *arg)
{
unsigned long i = 0;
pthread_t id = pthread_self();
if(pthread_equal(id,tid[0]))
{
printf("\n First thread processing\n");
}
else
{
printf("\n Second thread processing\n");
}
for(i=0; i<(0xFFFFFFFF);i++);
return NULL;
}
int main(void)
{
int i = 0;
int err;
while(i < 2)
{
err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
if (err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
else
printf("\n Thread created successfully\n");
i++;
}
sleep(5);
return 0;
}
Did you observe the ‘sleep()’ function being used? Did you get a question about why sleep() is being used? Well if you did then you are at the correct place to get the answer and if you did not then also its going to be a good read ahead.
If I remove the sleep() function from the code above and then try to compile and run it, I see the following output :
$ ./threads
Thread created successfully
First thread processing
Thread created successfully
Second thread processing
So we see that the log ‘Second thread processing’ is missing in case we remove the sleep() function.
So, why does this happen? Well, this happened because just before the second thread is about to be scheduled, the parent thread (from which the two threads were created) completed its execution. This means that the default tIhread in which the main() function was running got completed and hence the process terminated as main() returned.
Thread Termination
As already discussed above that each program starts with at least one thread which is the thread in which main() function is executed.
#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
The function above makes sure that its parent thread does not terminate until it is done. If we are not interested in the return value then we can set this pointer to be NULL.
If we classify on a broader level, then we see that a thread can terminate in three ways :
If the thread returns from its start routine.
If it is canceled by some other thread. The function used here is pthread_cancel().
If its calls pthread_exit() function from within itself.
The focus here would be on pthread_exit(). Its prototype is as follows :
#include <pthread.h>
void pthread_exit(void *rval_ptr);
So we see that this function accepts only one argument, which is the return from the thread that calls this function. This return value is accessed by the parent thread which is waiting for this thread to terminate.
C Thread Termination Example
Lets take an example where we use the above discussed functions :
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
pthread_t tid[2];
int ret1,ret2;
void* doSomeThing(void *arg)
{
unsigned long i = 0;
pthread_t id = pthread_self();
for(i=0; i<(0xFFFFFFFF);i++);
if(pthread_equal(id,tid[0]))
{
printf("\n First thread processing done\n");
ret1 = 100;
pthread_exit(&ret1);
}
else
{
printf("\n Second thread processing done\n");
ret2 = 200;
pthread_exit(&ret2);
}
return NULL;
}
int main(void)
{
int i = 0;
int err;
int *ptr[2];
while(i < 2)
{
err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
if (err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
else
printf("\n Thread created successfully\n");
i++;
}
pthread_join(tid[0], (void**)&(ptr[0]));
pthread_join(tid[1], (void**)&(ptr[1]));
printf("\n return value from first thread is [%d]\n", *ptr[0]);
printf("\n return value from second thread is [%d]\n", *ptr[1]);
return 0;
}