Thread: Issue with using malloc between threads for an array of structs

  1. #1
    Registered User
    Join Date
    Dec 2015
    Posts
    112

    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;
    }

  2. #2
    Registered User
    Join Date
    Dec 2015
    Posts
    112
    I believe I got my example to work. I think part of my confusion was the way the IDE was displaying the info. When I tried to read the different indexes of the array of struct2 it worked fine.

    In my working example I moved struct2 to the end of MyData. Would that have made a difference?

    I will add a mutex around the 3 structs to prevent two locations from accessing this same data. I will also free the memory when I'm done with it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Malloc a struct pointer inside an array of structs
    By arortell in forum C Programming
    Replies: 10
    Last Post: 10-22-2014, 03:50 PM
  2. Replies: 3
    Last Post: 03-31-2009, 12:34 PM
  3. glibc malloc() and Posix Threads
    By scioner in forum C Programming
    Replies: 1
    Last Post: 05-01-2008, 05:42 PM
  4. Malloc for an Array of Structs
    By pseudonoma in forum C Programming
    Replies: 3
    Last Post: 03-26-2008, 01:55 PM
  5. threads and memory issue
    By Anubhav in forum C Programming
    Replies: 6
    Last Post: 07-25-2006, 04:51 AM

Tags for this Thread