0

I am attempting to read different values from standard input and store them in variables located in a structure I created called the process structure.Then I will take the info in this structure and store it in a pointer variable in a priority queue structure. This process structure looks as follows:


typedef struct proc{


int creationTime;
int pid; 
int runTime;
int ioTime; 
int repeat;
}proc;

The Structure for my Priority queue is as follows:

// type of one element in a queue 

typedef struct _Queue_element {
  void *info; //<- THIS IS WHERE ALL INFO FROM THE PROCESS STRUCTURE WILL BE STORED WHEN ADDED TO THE QUEUE
  int priority;
  struct _Queue_element *next;
} *Queue_element;

//basic queue type

typedef struct Queue {
  Queue_element queue;                           
  Queue_element tail;                            
  Queue_element current;                        
  Queue_element previous;                        
  unsigned long queuelength;                        
  unsigned int elementsize;                      
  unsigned int duplicates;                     
  int (*compare) (const void *e1, const void *e2); 
  pthread_mutex_t lock;
  int priority_is_tag_only;    
} Queue;

Lastly This is the add element to queue function in a readymade queue package I am using.

static void nolock_add_to_queue(Queue *q, void *element, int priority) {

  Queue_element new_element, ptr, prev = NULL;

  if (! q->duplicates && ! q->compare) {
    fprintf(stderr, "If duplicates are disallowed, the comparison function must be specified in init_queue().\n");
    exit(1);
  }
  
  if (!q->queue ||
     (q->queue && (q->duplicates || !nolock_element_in_queue(q, element)))) {

    new_element = (Queue_element) malloc(sizeof(struct _Queue_element));
    if (new_element == NULL) {
      fprintf(stderr, "malloc() failed in function add_to_queue()\n");
      exit(1);
    }
    new_element->info = (void *)malloc(q->elementsize);
    if (new_element->info == NULL) {
      fprintf(stderr, "malloc() failed in function add_to_queue()\n");
      exit(1);
    }

    memcpy(new_element->info, element, q->elementsize);

    new_element->priority = priority;

    (q->queuelength)++;

    if (q->queue == NULL) {             // first element
      new_element->next = NULL;
      q->queue = new_element;
      q->tail = new_element;
    }
    else if (q->priority_is_tag_only) { // FIFO queue
      q->tail->next = new_element;
      q->tail = new_element;
      new_element->next = NULL;
    }
    else {                              // priority queue
      ptr=q->queue;
      while (ptr != NULL && priority <= ptr->priority) {
    prev = ptr;
    ptr = ptr->next;
      }

      if (! prev) {   // queue only had one element and new element
              // has higher priority
    new_element->next=q->queue;
    q->tail = q->queue;
    q->queue=new_element;
      }
      else {         // insert new element 
    new_element->next = prev->next;
    prev->next = new_element;
    if (new_element->next == NULL) {
      // new tail
      q->tail = new_element;
    }
      }
    }
    
    nolock_rewind_queue(q);
    
  }
}

What I am confused about Is how this add to queue function will correctly store the info from typedef struct proc; to the void *info variable in typedef struct _Queue_element;. Please let me know if this question is lacking any information such as other functions Included in my package or any other points I may clarify. Even if you are unable to provide specific solutions to my problem any materials I may read up on that could help me understand these topics will certainly be useful.

UPDATE: I have realized that this function does not need to be changed whatsoever. But am still confused as to how it will receive the info from proc.

JSONdaMAN
  • 1
  • 1
  • 1
    There is too much text in this post and not enough information about the actual problem. Nobody cares about the simulation being implemented. The core problem is there is a queue that needs to handle data it knows nothing about. That’s it. But you have confused the description. You said “ I am using a priority queue package already made for me by my instructor” and “This is my Code for adding an element to my queue.” Which is it, a ready-made queue package or a routines you are writing? – Eric Postpischil Oct 29 '22 at 19:41
  • 1
    In any case, `void *` is a classic way for handling arbitrary data. If the queue package takes a `void *` as a payload for a queue element, then all you need to do is allocate memory for your `proc` structure or for whatever data you want, fill that memory, and pass its address to the queue add routine as the `void *` payload. Whenever you get an element back from the queue, you use its `void *` payload to access your data. And free it when it is no longer needed. That’s it. – Eric Postpischil Oct 29 '22 at 19:42
  • I appreciate your clarification and have Updated my question appropriately. Sorry for the confusion:/ – JSONdaMAN Oct 29 '22 at 21:48
  • Re “how this add to queue function will correctly store the info”: The add-to-queue function does not store the data. It stores the pointer to the data. Your code can use the pointer to the data to access the data. – Eric Postpischil Oct 29 '22 at 22:00

1 Answers1

0

But am still confused as to how it [the function nolock_add_to_queue] will receive the info from proc.

Well, I would rather say that the same pieces of information certainly can be accessed both in the function nolock_add_to_queue, through its arguments, and outside it, through variables of the type proc. But let's analyse it calmly. I took the liberty to format the code a bit differently, maybe it will be more readable.

First, we have this typedef declaration:

typedef struct proc {
    // ...
} proc;

Here, we do two things:

  1. define a type struct proc,
  2. declare the identifier proc as an alias for this type.

Note that the second identifier proc means a different thing than the first identifier proc.

Next, we have this typedef declaration:

typedef struct _Queue_element {
    void *info; //<- THIS IS WHERE ALL INFO FROM THE PROCESS STRUCTURE WILL BE STORED WHEN ADDED TO THE QUEUE
    // ...
} *Queue_element;

Here, we also do two things:

  1. define a type struct _Queue_element,
  2. declare the identifier Queue_element as an alias for the pointer type struct _Queue_element *.

Next, we have this typedef declaration:

typedef struct Queue {
    Queue_element queue;
    // ...
} Queue;

Here, we also do two things:

  1. define a type struct Queue,
  2. declare the identifier Queue as an alias for this type.

Similarly as before, the second Queue is different from the first one.

Next, we have this function definition:

static void nolock_add_to_queue (Queue *q, void *element, int priority) {
    // ...
}

Here, we define a function nolock_add_to_queue that:

  1. is static,
  2. takes a variable of the pointer type Queue * as its first argument,
  3. takes a variable of the pointer type void * as its second argument,
  4. takes a variable of the type int as its third argument,
  5. returns nothing.

Finally, how it all works together?

The function nolock_add_to_queue takes a Queue * variable as its argument. What follows, this function has access to every member of the type Queue through this variable.

Also, this function takes a void * variable of as its argument. What follows, it has access to the same memory that this variable has access. Note that I've written "memory", not "variable of type" or "member of type". It is because a void * variable may be considered something like "a pointer variable to data of no type". For details on void *, you can see for example the question What does void* mean and how to use it?, the question Concept of void pointer in C programming, or the question What does void mean in C, C++, and C#?.

When nolock_add_to_queue is invoked, it accesses, among others, the member queue of Queue by using q->queue. queue could access its member info (it is not accessed directly in the function). As to proc, there is no usage of the members of it directly, but I suppose they are used in the code that invokes nolock_add_to_queue. The usage is most probably not needed, as the function operates on Queue and its elements, and not directly on the data that its elements hold.

If something what I've written is unclear, feel free to ask in the comments for clarification.

user20276305
  • 95
  • 1
  • 7