I'm confused on how to pass struct arguments to threads in the for loop.
When I try with this approach, I get garbage port values. When I try to change the struct to just astruct argstruct; without the pointer, the second port overwrites the first one so I get 200 200 printed.
Also, would I have to free the struct in main, Func, or both?
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
void* Func(void* pstruct);
typedef struct thread_args{
int port;
} astruct;
int main()
{
int peers[2] = {100,200};
pthread_t threads[2];
astruct *argstruct[2];
for (int i = 0; i < 2; i++) {
argstruct[i] = malloc(sizeof(astruct));
argstruct[i]->port = peers[i];
pthread_create(&threads[i],NULL,Func,&argstruct[i]);
}
for(int i = 0; i < 2; i++){
pthread_join(threads[i], NULL);
}
return 0;
}
void* Func(void* pstruct){
int port;
astruct *argstruct = (astruct *)pstruct;
port = argstruct->port;
printf("port: %d\n", port);
return 0;
}
I'm confused on how to pass struct arguments to threads in the for loop.
argstruct[i] elements are pointers, you don't need address operator:
pthread_create(&threads[i], NULL, Func, argstruct[i]);
Note that you wouldn't need memory allocation for this simple case, you can use a local array:
//...
astruct argstruct[2];
for (int i = 0; i < 2; i++) {
argstruct[i].port = peers[i];
pthread_create(&threads[i], NULL, Func, &argstruct[i]);
}
//...
Also, would I have to free the struct in main, Func, or both?
You should free it one time only. The procedure is always the same, you free it when you don't need it anymore, that can be in the the thread routine or in main.
In your example, you could very well free the memory after port = argstruct->port; as you no longer use it after this assignment:
void* Func(void* pstruct){
int port;
astruct *argstruct = (astruct *)pstruct;
port = argstruct->port;
free(argstruct); //<-- here
printf("port: %d\n", port);
return 0;
}
Related
I get "corrupted size vs prev_size" error whenever I allocate a dynamic memory in a thread. Whenever I allocate the memory in main() it works fine. But allocating dynamic memory in thread produces the error.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *fib(void *p);
struct mystruct
{
int *array;
int size;
};
int main(int argc, char *argv[])
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
struct mystruct obj;
obj.size = atoi(argv[1]);;
pthread_create(&tid, &attr, fib, (void *)&obj);
pthread_join(tid, NULL);
}
void *fib (void *p)
{
struct mystruct *x = (struct mystruct *)p;
x->array = (int *) malloc (x->size);
for (int i=0; i<x->size; i++){
x->array[i] = i;
printf("The array is = %d\n", x->array[i]);
}
}
I've added snapshot for details.
Thanks!
Try with the following line:
x->array = malloc (x->size*sizeof(int));
You need to allocate space for x->size integers. malloc accepts as parameter the number of bytes you need. And for n int you need n times the size in bytes of a single int.
Do not forget to return from the main.
I am working on a function that creates a thread and calculates the Fibonacci sequence to a certain user inputted value. For example, if a user enters 5, the output will be: 0 1 1 2 3 5
However, the sequence must be calculated in the created thread, and the results have to be printed out after the thread is exited.
I can create the thread and calculate the sequence, but I need to pass the array fibSequence[] back to the original thread using pthread_exit and pthread_join. I am having trouble figuring out the syntax and can't find any examples of people passing arrays through.
What I have so far:
I created a function fib_runner() that is called by a newly created thread. The Fibonacci sequence is created and placed into the array fibSequence[]. I need to pass this back through to the main function. I am temporarily printing out the sequence in the function, but it should be printed in the main.
Thank you!
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void* fib_runner(void* arg)
{
int *limit_ptr = (int*) arg;
int limit = *limit_ptr;
int fibSequence[limit];
int size = sizeof(fibSequence)/sizeof(fibSequence[0]);
printf("Size: %d\n", size);
fibSequence[0] = 0;
fibSequence[1] = 1;
for (int i = 2; i <= size; i++)
{
fibSequence[i] = fibSequence[i-1] + fibSequence[i-2];
}
for (int i = 0; i <= size; i++)
{
printf("%d ", fibSequence[i]);
}
pthread_exit(0);
}
int main(int argc, char **argv)
{
int limit;
printf("Enter Number: ");
scanf("%d", &limit);
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, fib_runner, &limit);
pthread_join(tid, NULL);
}
Currently, the array is a local variable, so it would go out of scope when the function exits. You need to dynamically allocate memory for it instead:
int *fibSequence = malloc(sizeof(int) * limit);
Then return this pointer from the function:
return fibSequence;
In your main function, you then pass the address of a pointer to receive this value. Then you can print the content of the array. When you're done, be sure to free it:
int *fibSequence;
pthread_join(tid, (void **)&fibSequence);
for (int i = 0; i < limit; i++)
{
printf("%d ", fibSequence[i]);
}
free(fibSequence);
Also, you don't need size in your thread function, since it is the same as limit, and the way you currently calculate it won't work anyway since you now have a pointer instead of an array. Your loop limit in fib_runner also goes one past the end of the array. The exit condition should be i < size, not i <= size.
you have to pass in a value of void * to pthread_exit which is pthread_exit(( void * ) &fibSequence, once that function is called the passed in value will populate the second argument to pthread_join, the second argument will be a pointer to a pointer void ** it will hold the values passed in to pthred_exit
All the threads running within a process share the same address space, file descriptors, stack and other process related attributes.
Threads are sharing memory by definition, they do not own anything except stack and local variables;
If you make fibSequence[limit] global then all threads will have access to it.
You can also declare fibSequence[limit] on the stack in main and pass pointer to it to your thread.
To pass multiple arguments it is convenient to wrap them up in a structure.
The solutions below employ:
struct arg_struct {
int limit;
int *ptrFib;
}args;
Program:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct arg_struct {
int limit;
int *ptrFib;
}args;
void* fib_runner(void* arg)
{
struct arg_struct *a = (struct arg_struct *) arg;
int size = a->limit;
int * fibSequence = a->ptrFib;
fibSequence[0] = 0;
fibSequence[1] = 1;
for (int i = 2; i <= size; i++){
fibSequence[i] = fibSequence[i-1] + fibSequence[i-2];
}
pthread_exit(0);
}
int main(int argc, char **argv)
{
int limit;
printf("Enter Number: ");
scanf("%d", &limit);
int fibSequence[limit];
struct arg_struct argF;
argF.limit = limit;
argF.ptrFib = fibSequence;
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, fib_runner, &argF);
pthread_join(tid, NULL);
for (int i = 0; i <= limit; i++){
printf("%d ", fibSequence[i]);
}
}
Output:
Enter Number: 5
0 1 1 2 3 5
The solution with global variable argF is of course possible but it is less elegant.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct arg_struct {
int limit;
int *ptrFib;
}args;
struct arg_struct argF;
void* fib_runner()
{
int size = argF.limit;
int * fibSequence = argF.ptrFib;
fibSequence[0] = 0;
fibSequence[1] = 1;
for (int i = 2; i <= size; i++){
fibSequence[i] = fibSequence[i-1] + fibSequence[i-2];
}
pthread_exit(0);
}
int main(int argc, char **argv)
{
int limit;
printf("Enter Number: ");
scanf("%d", &limit);
int fibSequence[limit];
argF.limit = limit;
argF.ptrFib = fibSequence;
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, fib_runner, NULL);
pthread_join(tid, NULL);
for (int i = 0; i <= limit; i++){
printf("%d ", fibSequence[i]);
}
}
I'm having a trouble passing a struct pointer into a function because I'm a bit confused with those pointers and references. I want to modify the thread.thread_num value from the thread_startfunction.
#include <stdio.h>
#include <stdlib.h> //malloc, free
#include <pthread.h>
#define N 5
// void *malloc(size_t);
struct thread {
pthread_t thread_id;
int thread_num;
// int thread_sum;
};
void *thread_start(void *thread)
{
struct thread *my_data;
my_data = (struct thread *)thread;
printf("num T: %i\n", my_data->thread_num);
my_data->thread_num=4;
printf("num T: %i\n", my_data->thread_num);
return NULL;
}
int main(int argc, char *argv[])
{
int i;
struct thread pthread_data;
struct thread *thread = &pthread_data;
thread->thread_num=2;
pthread_create(&thread->thread_id, NULL, thread_start, (void *)&thread);
printf("num: %i\n",thread->thread_num);
pthread_exit(NULL);
return 0;
}
But the value that print the main doesn't change (2).
And then I want to create an array of thread struct, but I don't know how exactly do that:
I guess it should be something like this:
int main(int argc, char *argv[])
{
int i;
struct thread pthread_data;
struct thread *thread[N-1] = &pthread_data; // I don't know how to manage this.
for(i=0; i<N; i++)
{
thread->thread_num=i;
pthread_create(&thread[i]->thread_id, NULL, thread_start, (void *)&thread[i]);
printf("num %i: %i\n",i,thread[i]->thread_num);
}
pthread_exit(NULL);
return 0;
}
Any thoughts?
I recommend you to read http://www.advancedlinuxprogramming.com/alp-folder/alp-ch04-threads.pdf
And here what you wanted:
#define N 5
typedef struct thread {
pthread_t thread_id;
int thread_num;
// int thread_sum;
} ThreadData;
void *thread_start(void *thread)
{
ThreadData *my_data = (ThreadData*)thread;
//there is no guarantee that prints will be in order
// we will use its initial thread->num ,cause it differs for each thread
//plus you will see how threads will behave
int order=my_data->thread_num;
printf("%i) before num T: %i\n",order, my_data->thread_num);
my_data->thread_num=4;
printf("%i) after assignment num T: %i\n",order ,my_data->thread_num);
return NULL;
}
int main(int argc, char *argv[])
{
int i;
ThreadData thread[N];
for(i=0; i<N; i++)
{
thread[i].thread_num=i;
pthread_create(&(thread[i].thread_id), NULL, thread_start, (void *)(thread+i));
}
//wait for all threads
for (i = 0; i < N; i++)
pthread_join(thread[i].thread_id, NULL);
//print results of each thread
for (i = 0; i < N; i++)
printf(" %i)thread: number %i\n",i,thread[i].thread_num);
return 0;
}
I can see multiple mistakes in your code.
First you have your pointers wrong. In the first example, it is enough to pass &pthread_data to pthread_create, &thread is the address of the thread pointer, so you are passing struct thread ** to your function instead of struct thread *. In the second example you should use (void *) thread[i]. &thread[i] is again struct thread **.
When you want each thread to write to its own thread data, then you should make an array of thread data, so that each thread has its own piece, else you will run into race conditions.
As others have already pointed out, you should call pthread_join before calling printf to ensure that the main thread will wait for all worker threads.
Also note that if you are calling pthread_join from other function that the one that spawned those threads, you have to ensure that the array of tread data will not go out of scope (in this case it would be probably better to use malloc or a global array).
You can't. As soon as main exits, which it does when you call pthread_exit, pthread_data ceases to exist, since it's local to the main function. So it can't be modified.
I have the following functions :
void *foo(void *i) {
int a = (int) i;
}
int main() {
pthread_t thread;
int i;
pthread_create(&thread, 0, foo, (void *) i);
}
At compilation, there are some errors about casting ((void *) i and int a = (int) i). How can I pass an integer as the last argument of pthread_create properly?
Building on szx's answer (so give him the credit), here's how it would work in your for loop:
void *foo(void *i) {
int a = *((int *) i);
free(i);
}
int main() {
pthread_t thread;
for ( int i = 0; i < 10; ++1 ) {
int *arg = malloc(sizeof(*arg));
if ( arg == NULL ) {
fprintf(stderr, "Couldn't allocate memory for thread arg.\n");
exit(EXIT_FAILURE);
}
*arg = i;
pthread_create(&thread, 0, foo, arg);
}
/* Wait for threads, etc */
return 0;
}
On each iteration of the loop, you're allocating new memory, each with a different address, so the thing that gets passed to pthread_create() on each iteration is different, so none of your threads ends up trying to access the same memory and you don't get any thread safety issues in the way that you would if you just passed the address of i. In this case, you could also set up an array and pass the addresses of the elements.
You can allocate an int on the heap and pass it to pthread_create(). You can then deallocate it in your thread function:
void *foo(void *i) {
int a = *((int *) i);
free(i);
}
int main() {
pthread_t thread;
int *i = malloc(sizeof(*i));
pthread_create(&thread, 0, foo, (void *) i);
}
You should cast the address of i (rather than the value of i as you do now) in the last argument of pthread_create().
pthread_create(&thread, 0, foo, (void *) &i);
^ is missing
And the casting is wrong in your function too. It should be:
int a = *((int*) i);
If you intend to read the value, you should also initialize i to some value in main() as it's uninitialized now.
2 Use proper definition for main():
int main(void)
or int main(int argc, char *argv[]) or its equivalent.
Old question, but I faced the same problem today, and I decided not to follow this path.
My application was really about performance, so I chose to have this array of ints declared statically.
Since I don't know a lot of applications where your pthread_join / pthread_cancel is in another scope than your pthread_create, I chose this way :
#define NB_THREADS 4
void *job(void *_i) {
unsigned int i = *((unsigned int *) _i);
}
int main () {
unsigned int ints[NB_THREADS];
pthread_t threads[NB_THREADS];
for (unsigned int i = 0; i < NB_THREADS; ++i) {
ints[i] = i;
pthread_create(&threads[i], NULL, job, &ints[i]);
}
}
I find it more elegant, more efficient, and you don't have to worry about freeing since it only lives in this scope.
While this is an old question there is one option missing when all you need is to pass a positive integer like a descriptor: you can pass it directly as the address, while it it a hack it works well and avoid allocating anything :)
NOTE: the size of the integer must match the size of a pointer on your OS but nowadays most systems are native 64bits.
#include <pthread.h>
#include <inttypes.h>
#include <stdio.h>
void *_thread_loop(void *p)
{
uint64_t n = (uint64_t)p;
printf("received %llu\n", n);
return NULL;
}
int main(int argc, char const *argv[])
{
pthread_t read_thread_id;
uint64_t n = 42;
pthread_create(&read_thread_id, NULL, _thread_loop, (void *)n);
pthread_join(read_thread_id, NULL);
return 0;
}
I am attempting on creating multiple threads that each thread calculates a prime. I am trying to pass a second argument to a function using thread create. It keeps throwing up errors.
void* compute_prime (void* arg, void* arg2)
{
here is my main() with the create thread. &primeArray[i] after &max_prime is giving me the errors.
for(i=0; i< num_threads; i++)
{
primeArray[i]=0;
printf("creating threads: \n");
pthread_create(&primes[i],NULL, compute_prime, &max_prime, &primeArray[i]);
thread_number = i;
//pthread_create(&primes[i],NULL, compPrime, &max_prime);
}
/* join threads */
for(i=0; i< num_threads; i++)
{
pthread_join(primes[i], NULL);
//pthread_join(primes[i], (void*) &prime);
//pthread_join(primes[i],NULL);
//printf("\nThread %d produced: %d primes\n",i, prime);
printf("\nThread %d produced: %d primes\n",i, primeArray[i]);
sleep(1);
}
the error i get is:
myprime.c: In function âmainâ:
myprime.c:123: warning: passing argument 3 of âpthread_createâ from incompatible pointer type
/usr/include/pthread.h:227: note: expected âvoid * (*)(void *)â but argument is of type âvoid * (*)(void *, void *)â
myprime.c:123: error: too many arguments to function âpthread_createâ
It works fine if i take out the second argument.
You can only pass a single argument to the function that you are calling in the new thread. Create a struct to hold both of the values and send the address of the struct.
#include <pthread.h>
#include <stdlib.h>
typedef struct {
//Or whatever information that you need
int *max_prime;
int *ith_prime;
} compute_prime_struct;
void *compute_prime (void *args) {
compute_prime_struct *actual_args = args;
//...
free(actual_args);
return 0;
}
#define num_threads 10
int main() {
int max_prime = 0;
int primeArray[num_threads];
pthread_t primes[num_threads];
for (int i = 0; i < num_threads; ++i) {
compute_prime_struct *args = malloc(sizeof *args);
args->max_prime = &max_prime;
args->ith_prime = &primeArray[i];
if(pthread_create(&primes[i], NULL, compute_prime, args)) {
free(args);
//goto error_handler;
}
}
return 0;
}
In case of std::thread, the user can pass arguments to the thread function in the following method
std::thread(funcName,arg1,arg2);
for instance,
//for a thread function,
void threadFunction(int x,int y){
std::cout << x << y << std::endl;
}
// u can pass x and y values as below
std::thread mTimerThread;
mTimerThread = std::thread(threadFunction,1,12);
This is the code of Manakarse , everything is really good but you need a
pthread_join(thread[i],NULL)
just to be sure all of threads will successfully execute before end of main thread("main will "waiting" while all of threads aren't finished yet)
;
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct
{
int stop_flag;
char name[30];
} _process_data;
typedef struct
{
int meter_no;
int port_no;
} _process_control;
typedef struct
{
_process_data *process_data;
_process_control *process_control;
} compute_prime_struct;
void *compute_prime (void *args)
{
compute_prime_struct *actual_args = args;
printf("actual_args->process_data->stop_flag [%d]\n",actual_args->process_data->stop_flag);
printf("actual_args->process_data->name [%s]\n",actual_args->process_data->name);
printf("actual_args->process_control->meter_no [%d]\n",actual_args->process_control->meter_no);
printf("actual_args->process_control->port_no [%d]\n",actual_args->process_control->port_no);
free(actual_args);
return 0;
}
void fill_data(_process_data *process_data,_process_control *process_control)
{
process_data->stop_flag=1;
process_data->name[0]='P';
process_control->meter_no=6;
process_control->port_no=22;
pthread_t tid;
compute_prime_struct *args = malloc(sizeof (*args));
args->process_data = malloc(sizeof (*args->process_data));
args->process_control = malloc(sizeof (*args->process_control));
memcpy (args->process_data, process_data, sizeof (args->process_data));
memcpy (args->process_control, process_control, sizeof (*args->process_control));
if(pthread_create(&tid, NULL, compute_prime, args))
{
free(args);
printf("Error here");
}
sleep(1);
}
int main()
{
_process_data process_data;
_process_control process_control;
fill_data(&process_data,&process_control);
return 0;
}