Matt Matt - 2 months ago 8
C Question

Extract sub struct from main struct for thread creation

I am having issues trying to send multiple arguments to the pthread_create, the issue is basically because one of the arguments is another struct.

This is the node.

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#define NUM_THREADS 4


struct arr {
char line[10];
};
struct args {
struct arr record; int count; int init; int end;
};

void* processarr(void *arguments)
{
int count; int init; int end;
struct args *argstmp=arguments;
init=argstmp->init;
count=argstmp->count;
end=argstmp->end;
struct arr record[count];
record=(struct arr)argstmp->record;

printf("Some of the vals are init %d count %d end %d\n",init, count, end);
printf("vals like record 0\n", record[0].line);
pthread_exit(NULL);
}/*end of processarr*/


int main (int argc, char *argv[])
{

int line_count;
FILE *ptr_file;
char buf[10];


ptr_file =fopen(argv[ 1 ],"r");
if (!ptr_file)
return 1;

while (fgets(buf,10, ptr_file)!=NULL)
{
line_count++ ;
}
rewind(ptr_file);
struct arr record[line_count];

line_count=0;
while (fgets(buf,10, ptr_file)!=NULL)
{
line_count++ ;
buf[strcspn(buf, "\r\n")] = 0; /* Removing end null chars*/
strcpy(record[line_count].line,buf);
}


float grptmp,group, lgroup;

grptmp=line_count/NUM_THREADS;

int counter1,counter2,init,end;
counter2=1;

struct args myargs;

//processarr(record, line_count, init, end);
pthread_t threads[NUM_THREADS];


for (counter1=0;counter1<=line_count;counter1++)
{
if(counter2==NUM_THREADS)
{
end=line_count;
}else{
end=counter1+grptmp;
}
init=counter1;
myargs.record=*record;
myargs.count=line_count;
myargs.init=init;
myargs.end=end;
printf ("Run job #%d with paramts Init=%d and End=%d\n",counter2, init, end);
//call here
//struct arr *record; int count; int init; int end;


int rc;
long t;
for(t=0;t<NUM_THREADS;t++){

rc = pthread_create(&threads[t], NULL,processarr,&myargs);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}

counter1=counter1+grptmp;
counter2++;

}

return 0;
}


So, when I send my arguments,the one stored inside myargs.record=*record, for some reason I am not able to "unpack" it once in the function.

The function is was defined as void to be able to catch the whole big argument, and I am trying to re-map everything there, the counts are working fine, but the one called record, that is actually another struct is not working, looks like a cast issue.

void* processarr(void *arguments)
{
int count; int init; int end;
struct args *argstmp=arguments;
init=argstmp->init;
count=argstmp->count;
end=argstmp->end;
struct arr record[count];
record=(struct arr)argstmp->record;

printf("Some of the vals are init %d count %d end %d\n",init, count, end);
printf("vals like record 0\n", record[0].line);
pthread_exit(NULL);
}


I am getting the following error when compiling.

test4.c: In function processarr:
test4.c:31:7: error: assignment to expression with array type
record=(struct arr)argstmp->record;


Any idea why this is not working? This last one was my last change using the casting (struct arr) in front of the argstmp (which is supposed to have everything inside).

Answer

Elaborating a little more on my response, this is what I would do using another struct to pass the arguments.

typedef struct {char line[10];}mystruct;
typedef struct {mystruct struct1;char line[10];}wrapper;
struct wrapper2 {mystruct struct1;char line[10];};

void unwrap(struct wrapper2 args){
printf("val is %s\n",args.line);
mystruct tmp=args.struct1;
printf("val inside structure is %s\n\n", tmp.line);
}

int main ()
{
mystruct names;
strcpy(names.line,"TEST");

struct wrapper2 wrapper1;
wrapper1.struct1=names;
strcpy(wrapper1.line,"Value1");
unwrap (wrapper1);
}

I hope this example helps you fix the issue, you just need to pass the same thing using the pthread_create.