Issue with using malloc between threads for an array of structs
I tried to simplify my problem and wrote a program exhibiting my issue. I'm trying to make use of a consumer/producer solution but have the consumer produce some data at the end. In my program I won't know the size of one of the structs and would like to allocate it during execution. My compiler is CVI and it does have some C99 functionality.
When I allocate struct2 in the function threadConsumer, it only creates a single struct and not an array of 10 of them. I need it to be a copy of the data that I got from the consumer thread. How do I get it to be an array of structs? It's almost being treated like a pointer to a single struct and I've tried doing a ** with no success either.
Code:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
//typedef enum { false, true } bool;
/**
* The Node struct,
* contains item and the pointer that point to next node.
*/
typedef struct Node {
int item;
struct Node* next;
} Node;
/**
* The Queue struct, contains the pointers that
* point to first node and last node, the size of the Queue,
* and the function pointers.
*/
typedef struct Queue {
Node* head;
Node* tail;
void (*push) (struct Queue*, int); // add item to tail
// get item from head and remove it from queue
int (*pop) (struct Queue*);
// get item from head but keep it in queue
int (*peek) (struct Queue*);
// display all element in queue
void (*display) (struct Queue*);
// size of this queue
int size;
} Queue;
/**
* Push an item into queue, if this is the first item,
* both queue->head and queue->tail will point to it,
* otherwise the oldtail->next and tail will point to it.
*/
void push (Queue* queue, int item);
/**
* Return and remove the first item.
*/
int pop (Queue* queue);
/**
* Return but not remove the first item.
*/
int peek (Queue* queue);
/**
* Show all items in queue.
*/
void display (Queue* queue);
/**
* Create and initiate a Queue
*/
Queue createQueue ();
typedef struct TestStruct1{
int iTest;
} TestStruct1;
typedef struct TestStruct2{
int iTest;
} TestStruct2;
typedef struct TestStruct3{
int iTest;
} TestStruct3;
DWORD WINAPI threadConsumer(void*);
DWORD WINAPI threadProducer(void*);
#define GETMYRAND() (int)(((double)rand()/(double)RAND_MAX)*100)
typedef struct MyData{
Queue food;
int producerfinished;
HANDLE mutex;
HANDLE controlsemaphore;
TestStruct1 struct1;
TestStruct2 *struct2;
TestStruct3 struct3;
}MyData;
int main(int argc, char** argv)
{
HANDLE handles[2];
MyData mydata;
mydata.mutex = CreateMutex(NULL, 0, NULL);
mydata.controlsemaphore = CreateSemaphore(NULL,0,1,NULL);
mydata.producerfinished=0;
mydata.food = createQueue();
handles[0] = CreateThread(0,0,&threadConsumer, (void*)&mydata, 0,0);
handles[1] = CreateThread(0,0,&threadProducer, (void*)&mydata, 0,0);
WaitForMultipleObjects(2, handles, 1, INFINITE); //"Join" trreads
CloseHandle(mydata.mutex);
CloseHandle(mydata.controlsemaphore);
free(mydata.struct2);
return 0;
}
DWORD WINAPI threadConsumer(void* lp){
MyData * md = (MyData*)lp;
TestStruct1 struct1;
TestStruct2 *struct2;
TestStruct3 struct3;
int iStructSize = 0;
int i = 0;
while(!md->producerfinished){
Sleep(GETMYRAND());
WaitForSingleObject(md->controlsemaphore,INFINITE); //Wait for producer;
WaitForSingleObject(md->mutex, INFINITE); //Mutext Lock
while(md->food.size>0){
char tmps[32];
sprintf(tmps, "\t%d\t(%d)\n",md->food.peek(&md->food), GetCurrentThreadId());
//cout<<tmps;
printf(tmps);
if(md->food.peek(&md->food) == 0)
struct1.iTest = md->food.peek(&md->food);
else if(md->food.peek(&md->food) > 9 && md->food.peek(&md->food) < 21)
{
if(iStructSize == 0)
struct2 = calloc(++iStructSize, sizeof(TestStruct2));
else
struct2 = realloc(struct2, (++iStructSize * sizeof(TestStruct2)));
struct2[iStructSize - 1].iTest = md->food.peek(&md->food);
}
else if(md->food.peek(&md->food) == 50)
struct3.iTest = md->food.peek(&md->food);
md->food.pop(&md->food);
}
ReleaseMutex(md->mutex); //Mutex Unlock
}
md->struct1 = struct1;
md->struct3 = struct3;
md->struct2 = calloc(10, sizeof(TestStruct2));
for(i = 0; i < 10; i++)
{
md->struct2[i] = struct2[i];
}
return 0;
}
DWORD WINAPI threadProducer(void* lp){
MyData * md = (MyData*)lp;
int i;
for(i =0 ; i < 100; i++){
char tmps[32];
sprintf(tmps, "%d\t\t%d\n",i,GetCurrentThreadId());
//cout<<tmps;
printf(tmps);
Sleep(GETMYRAND());
WaitForSingleObject(md->mutex, INFINITE); //Mutex Lock
md->food.push(&md->food, i);
if(md->food.size>0 && i > 10)
ReleaseSemaphore(md->controlsemaphore,1, NULL);
ReleaseMutex(md->mutex); //Mutex Unlock
}
md->producerfinished=1;
ReleaseSemaphore(md->controlsemaphore, 1, NULL); //Release both threads
return 0;
}
/**
* Push an item into queue, if this is the first item,
* both queue->head and queue->tail will point to it,
* otherwise the oldtail->next and tail will point to it.
*/
void push (Queue* queue, int item) {
// Create a new node
Node* n = (Node*) malloc (sizeof(Node));
n->item = item;
n->next = NULL;
if (queue->head == NULL) { // no head
queue->head = n;
} else{
queue->tail->next = n;
}
queue->tail = n;
queue->size++;
}
/**
* Return and remove the first item.
*/
int pop (Queue* queue) {
// get the first item
Node* head = queue->head;
int item = head->item;
// move head pointer to next node, decrease size
queue->head = head->next;
queue->size--;
// free the memory of original head
free(head);
return item;
}
/**
* Return but not remove the first item.
*/
int peek (Queue* queue) {
Node* head = queue->head;
return head->item;
}
/**
* Show all items in queue.
*/
void display (Queue* queue) {
printf("\nDisplay: ");
// no item
if (queue->size == 0)
printf("No item in queue.\n");
else { // has item(s)
Node* head = queue->head;
int i, size = queue->size;
printf("%d item(s):\n", queue->size);
for (i = 0; i < size; i++) {
if (i > 0)
printf(", ");
printf("%d", head->item);
head = head->next;
}
}
printf("\n\n");
}
/**
* Create and initiate a Queue
*/
Queue createQueue () {
Queue queue;
queue.size = 0;
queue.head = NULL;
queue.tail = NULL;
queue.push = &push;
queue.pop = &pop;
queue.peek = &peek;
queue.display = &display;
return queue;
}