I simply want to pass the value of an integer to a thread.
How can I do that?
I tried:
int i;
pthread_t thread_tid[10];
for(i=0; i<10; i++)
{
pthread_create(&thread_tid[i], NULL, collector, i);
}
The thread method looks like this:
void *collector( void *arg)
{
int a = (int) arg;
...
I get the following warning:
warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
The compiler will complain if you don't cast i to a void pointer:
pthread_create(&thread_tid[i], NULL, collector, (void*)i);
That said, casting an integer to a pointer isn't strictly safe:
ISO/IEC 9899:201x
6.3.2.3 Pointers
An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.
so you're better off passing a separate pointer to each thread.
Here's a full working example, which passes each thread a pointer to a separate element in an array:
#include <pthread.h>
#include <stdio.h>
void * collector(void* arg)
{
int* a = (int*)arg;
printf("%d\n", *a);
return NULL;
}
int main()
{
int i, id[10];
pthread_t thread_tid[10];
for(i = 0; i < 10; i++) {
id[i] = i;
pthread_create(&thread_tid[i], NULL, collector, (void*)(id + i));
}
for(i = 0; i < 10; i++) {
pthread_join(thread_tid[i], NULL);
}
return 0;
}
There's a nice intro to pthreads here.
int is 32 bit, and void * is 64 bit in 64bit Linux; In that case you should use long int instead of int;
long int i;
pthread_create(&thread_id, NULL, fun, (void*)i);
int fun(void *i) function
long int id = (long int) i;
void *foo(void *i) {
int a = *((int *) i);
free(i);
}
int main {
int *arg = (char*)malloc(sizeof(char))
pthread_create(&thread, 0, foo, arg);
}
It better to use of a struct for send more parameters in one :
struct PARAMS
{
int i;
char c[255];
float f;
} params;
pthread_create(&thread_id, NULL, fun, (void*)(¶ms));
then you can cast params to PARAMS* and use of it in pthread routine:
PARAMS *p = static_cast<PARAMS*>(params);
p->i = 5;
strcpy(p->c, "hello");
p->f = 45.2;
Related
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
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
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.
My code is not working... But another example that is similar to my code is working. How can I fix?
It seems like pthread_join() is internally change integer value like my code. But mine does not work.
Can anybody help me to fix?
#include <stdio.h>
void test(void **temp) {
int foo = 3;
*temp = foo;
}
int main(void) {
int temp;
test((void **)&temp);
printf("%d\n", temp);
return 0;
}
pthread_join example:
#include <pthread.h>
#include <stdlib.h>
void *test(void *data) {
int i;
int a = *(int *)data;
for (i = 0; i < 10; i++) {
printf("%d\n", i * a);
}
}
int main() {
int a = 100;
pthread_t thread_t;
int status;
if (pthread_create(&thread_t, NULL, test, (void *)&a) < 0) {
perror("thread create error:");
exit(0);
}
pthread_join(thread_t, (void **)&status);
printf("Thread End %d\n", status);
return 1;
}
But mine does not work..
This statement:
pthread_join(thread_t, (void **)&status);
assigns to status the return value of your thread function. But your function doesn't return anything, so you get garbage.
To fix this, make your test function return something.
P.S. Please do turn on compiler warnings (-Wall, -Wextra) -- the compiler should have warned you of the bug already.
P.P.S Please do not name your variables like this: thread_t -- the _t stands for type, and thead_t is not a type.
You are trying to make temp into two void pointers (void**) when you actually only have one pointer to the int temp. Just return the pointer value and you can use this in a similar pthread example.
#include <stdio.h>
#include <stdlib.h>
void *test(void *temp) {
int *ptr = (int*)malloc(sizeof(int));
*ptr = 3;
return ptr;
}
int main(int argc, char *argv[]) {
int *temp = (int*)test(nullptr);
printf("%d\n", *temp);
free(temp);
return 0;
}
I have just started learning parallel programming using pthreads. So, for the learning purpose I tried sum of two integer arrays parallely. I have declared struct construct with three array variables a, b and c. I want to do addition of a, b and store the result in c.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define MAX 6
struct data {
int a[MAX];
int b[MAX];
int c[MAX];
};
void *addition(void *index) {
struct data *d1 = (struct data *)index;
printf("value of d1 structure=%d\n", d1->a[0]);
}
int main() {
int i, j, t;
struct data *item = NULL;
pthread_t threads[MAX];
item = (struct data *)malloc(sizeof *item);
printf("enter the value for arrray a\n");
for (i = 0; i < MAX; i++) {
scanf("%d", &item->a[i]);
}
printf("enter the value of array b\n");
for (j = 0; j < MAX; j++) {
scanf("%d", &item->b[j]);
}
for (t = 0; t < MAX; t++) {
pthread_create(&threads[t], NULL, addition, (void *)&item);
}
}
Here, as of now I have not added the addition of arrays in the function addition(), because in pthread_create() when I am passing the three arguments with the help of structure, in function addition the variables a and b are not getting copied. Printing a is giving me garbage value. Can anybody help me how to copy the structure variable to the function argument called by pthread_create().
pthread_create Function :
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Kindly note (*arg) is pointer to the arg.
You have created struct data *item as a pointer then you are passing its address i.e. pointer to pointer.
pthread_create(&threads[t], NULL, addition, (void *)&item);
Change the call to
pthread_create(&threads[t], NULL, addition, (void *)item).
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;
}
Is it possible to cast a pointer to an unsigned int, then later cast it back to a pointer? I'm trying to store the pointer to a struct in a pthread_t variable, but I can't seem to get it to work. Here's some snippets of my code (I'm creating a user-level thread management library). When I try to print out the tid of the thread it gives me some long garbage number.
Edit: Never mind, I got it to work.
I changed
thread = (pthread_t) currentThread;
to
*thread = (pthread_t) currentThread;
Figured it was something stupid like that.
Test program:
pthread_t thread1;
pthread_t thread2;
pthread_create(&thread1, NULL, runner, NULL);
pthread_create(&thread2, NULL, runner, NULL);
pthread_join(&thread2, NULL);
My library:
typedef struct queueItem
{
int tid;
ucontext_t context;
int caller;
struct queueItem *joiningOn;
struct queueItem *nextContext;
} queueItem;
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg)
{
thread = (pthread_t) currentThread;
}
...
int pthread_join(pthread_t thread, void **retval)
{
queueItem *t = (queueItem *) thread;
if(runningContext->joiningOn != NULL) // Current thread is already waiting on another
return EINVAL;
if(t == NULL) // If thread to join on is invalid
return 0;
fprintf(stdout, "JOINEE: %d\n", t->tid); // Prints weird number
runningContext->caller = JOIN;
runningContext->joiningOn = t;
swapcontext(&(runningContext->context), &scheduleContext);
}
No. On many systems pointer type is bigger than int type. If you have a problem to use pthread_t, ask about it, int is not the answer.
For example, on my machine, the following code:
#include <stdio.h>
int main() {
printf("unsigned int = %lu\n", sizeof(unsigned int));
printf("pointer = %lu\n", sizeof(void*));
return 0;
}
outputs:
unsigned int = 4
pointer = 8
Sure it's possible, if you make sure your unsigned int is the same size as a void* on your system.
If you have some code that's not working, post it.
Edit: You should read about intptr_t, e.g. here: Why / when to use `intptr_t` for type-casting in C?