2

Possible Duplicate:
Multiple arguments to function called by pthread_create()?
How to pass more than one value as an argument to a thread in C?

I have these structures:

struct Request {
    char buf[MAXLENREQ];
    char inf[MAXLENREQ]; /* buffer per richiesta INF */
    int lenreq;
    uint16_t port; /* porta server */
    struct in_addr serveraddr; /* ip server sockaddr_in */
    char path[MAXLENPATH];
    /*struct Range range;*/
};

struct RequestGet {
    char buf[MAXLENREQ];
    int maxconnect;
    struct Range range;
};

struct ResponseGet{
    char buf[MAXLENDATA];
    //int LenRange;
    int expire;
    char dati[MAXLENDATA];
    struct Range range; 
};

How can I pass them to pthread_create? No matter about the meanings of each field of structures.

pthread_create(&id,NULL,thread_func,????HERE????);
Community
  • 1
  • 1
rschirin
  • 1,939
  • 10
  • 34
  • 44
  • I've seen it, but my doubt was about the malloc of three different structures... – rschirin Jan 23 '12 at 18:33
  • possible duplicate of [Multiple arguments to function called by pthread_create()?](http://stackoverflow.com/questions/1352749/), [pthreads and C++](http://stackoverflow.com/questions/2468113/), [Passing multiple arguments to a thread in C (pthread_create)](http://stackoverflow.com/questions/6524433/) – outis Jan 24 '12 at 03:59

5 Answers5

7

You can only pass one parameter, so you generally need to make a function that takes one parameter, even if it just wraps some other calls. You can do this by creating a struct and having the function take a pointer to such a struct.

A basic example to illustrate the point is below. Please note that it is not a complete example, and should not be used as-is! Note, for example, that none of the memory allocated with malloc() is freed.

struct RequestWrapper {
    struct Request *request;
    struct RequestGet *request_get;
    struct ResponseGet *response_get;
};

void thread_func(struct RequestWrapper *rw) {
    // function body here
}

int main(int argc, char *argv[]) {
    struct Request *request = malloc(sizeof(*request));
    struct RequestGet *request_get = malloc(sizeof(*request_get));
    struct ResponseGet *response_get = malloc(sizeof(*response_get));
    ...

    struct RequestWrapper *wrapper = malloc(sizeof(*wrapper));

    wrapper->request = request;
    wrapper->request_get = request_get;
    wrapper->response_get = response_get;

    ...

    pthread_create(&id, NULL, thread_func, &wrapper);
    ...
}
Dan Fego
  • 13,644
  • 6
  • 48
  • 59
  • Dangerously incomplete. See my comment to spraff. – R.. GitHub STOP HELPING ICE Jan 23 '12 at 18:19
  • @R.. The idea is to get him started with the concept he doesn't understand, not to write a whole bunch of other code. The best examples are, admittedly, the ones that run as-is, but this gets the idea across as to how to pass in multiple things, and I think it conveys that appropriately. I'll add a note in, however, pointing out its incompleteness. – Dan Fego Jan 23 '12 at 18:20
  • Well the problem is that you're "getting him started" with code that will probably work 99% of the time and crash or horribly corrupt memory the other 1% of the time. Beginners are unlikely to realize this, much less know how to go back and fix it.. – R.. GitHub STOP HELPING ICE Jan 23 '12 at 18:22
  • In particular, you could simply edit your example to use `malloc` rather than a local var for the struct, and the example would remain just about as simple, but would no longer be dangerous. – R.. GitHub STOP HELPING ICE Jan 23 '12 at 18:23
  • @R.. Fair enough. Reflected above. – Dan Fego Jan 23 '12 at 18:27
  • @R.. the risk is due to the fact that you should do the free function into the thread? – rschirin Jan 23 '12 at 18:48
  • My point is that if you pass a pointer to a structure that's an automatic (local, non-static) variable in one thread to another thread, there's a danger that the pointer will become invalid (due to the function in the parent thread returning, and the lifetime of its automatic variables ending) before the new thread finishes using it. Using `malloc` to allocate the structure in the parent thread and then `free`ing it once you're done in the new thread is a safe and simple way to handle the issue. – R.. GitHub STOP HELPING ICE Jan 23 '12 at 18:58
2
struct Foo {
   // anything you want
};

void run (void * _arg) {
    Foo * arg = (Foo*) _arg;
    // ...
}

int main () {
    pthread_t thread;
    Foo * foo = create_argument ();

    pthread_create (&thread, NULL, run, foo);
}

This depends, of course, on a contract that run will always be given a Foo* in the last argument to pthread_create.

spraff
  • 32,570
  • 22
  • 121
  • 229
  • 1
    This answer is dangerously incomplete; as written, `foo`'s lifetime potentially ends before `run` is able to use it. You must either allocate the space for `foo` with `malloc` (and `free` it in the new thread, not the parent thread!) or use some synchronization objects (barrier or semaphore is easiest) to ensure that `foo`'s lifetime does not end too soon. – R.. GitHub STOP HELPING ICE Jan 23 '12 at 18:18
0

The last argument of pthread_create() is a void pointer. Its designation is that you can let it point to whatever kind of variable, struct etc. Your thread_func knows how to handle it and can cast it back to its original type.

ypnos
  • 50,202
  • 14
  • 95
  • 141
0

Put their addresses into a struct, and pass a pointer to that struct as the last argument to pthread_create().

NPE
  • 486,780
  • 108
  • 951
  • 1,012
0

you can just create a structure for all data and pass the address of the structure. you may need to put the structure in the heap and free it when done.

justin
  • 104,054
  • 14
  • 179
  • 226