1

I am playing with a custom threads api, i want to spawn a new thread with two pointers to message channels and an integer.

spawn_thread(Proctype Procedure, int argc, char *argv[]);

I am using 'channels' as an shared area between threads.

i have three variables: `Chan *return, Chan *receive and an int n'

Could i simply cast all of the values i want to store in *argv[], to chars? The reason i haven't done this is the width of the char is only 8 bits so a max value of 255, which isn't enough to hold pointer or large values.

Babbleshack
  • 341
  • 1
  • 5
  • 16
  • 1
    If you want to have generic pointers, use `void *` instead of `char *`. – Shahbaz Feb 10 '14 at 14:23
  • problem is i dont want to pass n as a pointer, i want to pass to actual value of 'n'. – Babbleshack Feb 10 '14 at 14:26
  • That's not a good idea. Even if you pass the actual value of `n` and receive it with another type on the function, and even if you make sure you don't access it with that other representation, and even if you could make sure `n` always fits in the other type, you still won't achieve much. What's the point of an API where you can send the value of an integer or a char or a float, but not the value of a bigger struct or an array? When designing, try to minimize exceptions. If your design says: _You can do this with these types, but not those_, you are doing something wrong. – Shahbaz Feb 10 '14 at 14:35
  • 1
    Incidentally, that's a mistake that's all over Java's design. _You can have references to objects, but not variables of basic types_. _You can pass by value, but only variables of basic types_. _You can have templates only of class types, but not basic types_. And then there are a whole set of exceptions just for arrays. You'd do well by learning from the mistake that is Java and design your API so it would be exception-free. – Shahbaz Feb 10 '14 at 14:37
  • agreed, but i am doing an assignment and the api is provided, i simply 'made it work'. thanks for the commment, and ill take it into account cause you make a valid point. I think ill use the structure from the accepted answer as it follows the api, but as an extra task ill improve the api. paying attention to your your java comment too. – Babbleshack Feb 10 '14 at 14:39

2 Answers2

2

One common approach to storing heterogeneous data in a C array is with tagged unions:

typedef enum {chDataReturn, chDataReceive, chDataInt} ChannelDataType;
struct ChannelData {
    ChannelDataType type;
    union {
         ChanReturn ret;
         ChanReceive rcv;
         int num;
    } data;
};

Now your spawn_thread prototype would look as follows:

spawn_thread(Proctype Procedure, int argc, struct ChannelData *argv);

Users would put the data into the array of argvs, "tagging" each item with its type, like this:

struct ChannelData *data = malloc(3*sizeof(struct ChannelData));
data[0].type = chDataReturn;
data[0].data.ret = myReturn;
data[1].type = chDataReceive;
data[1].data.ret = myReceive;
data[2].type = chDataInt;
data[3].data.num = 12345;
spawn_thread(myProc, 3, data);
// Wait for the thread to finish, and then...
...
free(data);
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

char * argv[] passes a char ** which you can just as easily cast to a void ** essentially allowing you to pass an array of void * to whatever you like.

char * argv[] = {&return, &receive, &n};
spawn_thread(Procedure, 3, argv);

Procedure(int argc, char *argv[]) {
    char return = *argv[0];
    char receive = *argv[1];
    int return = *(int *)argv[2];

    // ...
}
Sergey L.
  • 21,822
  • 5
  • 49
  • 75
  • Actually `void **` and `char **` are not necessarily compatible (although they most likely are). http://stackoverflow.com/q/11275713/912144 – Shahbaz Feb 10 '14 at 14:22