I have found several codes using dynamic memory allocation method for passing an integer as the last argument, like this example:
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;
}
Otherwise, I found academic examples that use an array method, like this example passing a struct:
//Runnable example
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct my_Struct{
int index;
int value;
};
void* my_Func(void *received_struct){
struct my_Struct *struct_ptr = (struct my_Struct*) received_struct;
printf("index: %d | value: %d \n", struct_ptr->index, struct_ptr->value);
//Now use 'struct_ptr->index', 'struct_ptr->value' as you wish
}
int main(){
struct my_Struct mystruct_1[5];
printf("\nEnter 5 numbers:\n");
for (int i=0; i<5; i ){
scanf("%d", &mystruct_1[i].value);
mystruct_1[i].index = i;
}
pthread_t tid[5];
for(int i=0; i<5; i ){
pthread_create(&(tid[i]), NULL, my_Func, &mystruct_1[i]);
}
for (int i=0; i<5; i ){
pthread_join(tid[i], NULL);
}
}
//To run: gcc [C FILE].c -lpthread -lrt
// ./a.out
//Grepper Profile: https://www.codegrepper.com/app/profile.php?id=9192
What is the advantage of the dynamic memory allocation method?
Update: I found in the IBM i documentation, based on gcc, that they use memory allocation
CodePudding user response:
When you only want to pass one integer you can just cast it to a pointer:
void *foo(void *i) {
int a = (int)i;
}
for ( int i = 0; i < 10; 1 ) {
pthread_create(&thread, 0, foo, (void*)i);
}
This gives maximum efficiency and no lifetime concerns.
CodePudding user response:
The last parameter of pthread_create()
is passed on the stack of the newly created thread. When it is an integer or anything else which the size is little or equal than the size of a pointer, the parameter can be passed as it is to pthread_create()
with a cast. But it is not the recommended way to make it as it is not portable on machines where for example the integers do not have the same size as the pointers. Let's compile the following simple program:
#include <pthread.h>
#include <stdio.h>
void* thread_task(void* arg)
{
printf("Thread received parameter: %d\n", (int)arg);
return NULL;
}
int main(void)
{
pthread_t tid;
int i = 45;
pthread_create(&tid, NULL, thread_task, (void *)i);
pthread_join(tid, NULL);
return 0;
}
The gcc compiler raises the following warnings:
$ gcc pcreate.c -o pcreate -lpthread
pcreate.c: In function ‘thread_task’:
pcreate.c:6:45: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
printf("Thread received parameter: %d\n", (int)arg);
^
pcreate.c: In function ‘main’:
pcreate.c:15:43: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
pthread_create(&tid, NULL, thread_task, (void *)i);
Hence, using a pointer on a structure or a table entry or a dynamically allocated memory area is the way to make it portable. The preceding program could be fixed as:
#include <pthread.h>
#include <stdio.h>
void* thread_task(void* arg)
{
printf("Thread received parameter: %d\n", *((int *)arg));
return NULL;
}
int main(void)
{
pthread_t tid;
int t[1] = { 45 };
pthread_create(&tid, NULL, thread_task, (void *)t);
pthread_join(tid, NULL);
return 0;
}
The compiler no longer raises any warnings:
$ gcc pcreate.c -o pcreate -lpthread
$ ./pcreate
Thread received parameter: 45