title: Queue in C via array
body: <p>I have implemented a queue in C language with usage of an array of structures.</p>
  
  <pre><code>typedef struct{
      req_t     buffer[BUFFER_SIZE];   // buffer
      uint16_t    size;                          // length of the queue
      uint16_t    count;                 // number of elements present in the queue
      req_t     *p_head;                 // pointer to head of the queue (read end)
      req_t     *p_tail;                 // pointer to tail of the queue (write end)
  }circular_buffer_t;
  
  void init_cb(circular_buffer_t *p_cb){
  
      p_cb-&gt;p_head = p_cb-&gt;buffer;
      p_cb-&gt;p_tail = p_cb-&gt;buffer;
      p_cb-&gt;count = 0;
      p_cb-&gt;size = BUFFER_SIZE;
  
  }
  </code></pre>
  
  <p>The problem is that above given implementation is usable only for storing the 
  instances of req_t structures. Now I need to store instances of another 
  structure and I don't know how to define the queue in more general way so that 
  I will be able to use same queue for instances of different structures. Problem
  is that I need to know the structure type before buffer definition. Does anybody
  have any idea how to solve that?</p>
  
  <pre><code>    #ifndef CIRCULAR_BUFFER_H_
  #define CIRCULAR_BUFFER_H_
  
  #define BUFFER_SIZE 32
  
  // macro creates variant of the queue for each struct type
  #define define_queue(TYPE)                                                       \
                                                                                 \
    // queue element definition                                                  \                                                                                
    typedef struct{                                                              \
      TYPE     buffer[BUFFER_SIZE];                                              \
      uint16_t size;                                                             \
      uint16_t count;                                                            \
      TYPE     *p_head;                                                          \
      TYPE     *p_tail;                                                          \
    }circular_buffer_##TYPE##_t                                                  \
                                                                                 \
                                                                                 \
    // queue init function definition                                            \                                                                               
    void init_cb_##TYPE(circular_buffer_##TYPE##_t *p_cb){                       \
      p_cb-&gt;p_head = p_cb-&gt;buffer;                                               \
        p_cb-&gt;p_tail = p_cb-&gt;buffer;                                               \
        p_cb-&gt;count = 0;                                                           \
        p_cb-&gt;size = BUFFER_SIZE;                                                  \
    }                                                                            \
                                                                                 \
    // queue enqueue function definition                                         \                                                                               
    BOOL enqueue_cb_##TYPE(circular_buffer_##TYPE##_t *p_cb, TYPE *p_enq_elem){  \
                                                                                 \    
      if(p_cb-&gt;count &lt; p_cb-&gt;size){                                              \
                                                                                 \
           taskENTER_CRITICAL();                                                     \
                                                                                 \
              *(p_cb-&gt;p_tail) = *p_enq_elem;                                           \
              p_cb-&gt;p_tail = ((++(p_cb-&gt;p_tail) == (p_cb-&gt;buffer + p_cb-&gt;size)) ?      \
                        (p_cb-&gt;buffer) : (p_cb-&gt;p_tail));                        \
              p_cb-&gt;count++;                                                           \
                                                                                 \
           taskEXIT_CRITICAL();                                                      \
                                                                                 \
           return TRUE;                                                              \
                                                                                 \
        }else{                                                                     \
                                                                                 \
           return FALSE;                                                             \
                                                                                 \
        }                                                                          \
                                                                                 \
    }                                                                            \
                                                                                 \
    // queue dequeue function definition                                         \                                                                               
    BOOL dequeue_cb_##TYPE(circular_buffer_##TYPE##_t *p_cb, TYPE *p_deq_elem){  \
                                                                                 \
      if((p_cb-&gt;count) != 0){                                                    \
                                                                                 \
          taskENTER_CRITICAL();                                                      \
                                                                                 \
              *p_deq_elem = *(p_cb-&gt;p_head);                                           \
              p_cb-&gt;p_head = ((++(p_cb-&gt;p_head) == (p_cb-&gt;buffer + p_cb-&gt;size)) ?      \
                        (p_cb-&gt;buffer) : (p_cb-&gt;p_head));                        \
              p_cb-&gt;count--;                                                           \
                                                                                 \
          taskEXIT_CRITICAL();                                                       \
                                                                                 \
          return TRUE;                                                               \
                                                                                 \
       }else{                                                                      \
                                                                                 \
          return FALSE;                                                              \
                                                                                 \
       }                                                                           \
                                                                                 \
    }                                                                            \
  
  
  // macros for functions declarations
  #define declare_init_cb(TYPE)    void init_cb_##TYPE(circular_buffer_##TYPE##_t *p_cb)
  #define declare_enqueue_cb(TYPE) BOOL enqueue_cb_##TYPE(circular_buffer_##TYPE##_t *p_cb, TYPE p_enq_elem);
  #define declare_dequeue_cb(TYPE) BOOL dequeue_cb_##TYPE(circular_buffer_##TYPE##_t *p_cb, TYPE p_deq_elem);                                                
  
  #endif
  </code></pre>
  
  <p>Structures I am going to use with the queue</p>
  
  <pre><code>    typedef struct{
      uint32_t addr;          // address of the alarm signal
      BOOL     critical;      // alarm is critical (=TRUE), alarm is non critical (=FALSE)
      BOOL     set;           // alarm was set     (=TRUE)
      BOOL     cleared;       // alarm was cleared (=TRUE)
      BOOL     communicated;  // alarm is communicated to Main Controller (=TRUE)
      uint8_t  code;          // alarm code   (0 - 255) - permanently 180
      uint8_t  no;            // alarm number (0 - 255)
      uint8_t  no_flashes;    // number of LED flashes if the alarm is active
  }alarm_t;
  </code></pre>
  
  <p>and</p>
  
  <pre><code> typedef struct{
      msg_e req_type;                              // request type
      uint8_t         blk_no;                      // block number
      uint8_t         no_records;                  // number of influenced records
      uint8_t         data_id[MAX_NO_RECORDS];     // data id, max. number of records in one block
      uint16_t        value[MAX_NO_RECORDS];       // written value, max. number of records in one block
      uint8_t         cleared_alarm_no;            // number of the alarm which should be cleared
      uint8_t         flash_load;                  // 0 = Go into flash load mode
      uint8_t         mode[6];                     // 000000 - Normal, BOOTBL - Boot block
      uint8_t         data_block[BLOCK_SIZE];      // one block in flash memory
      uint8_t         flash_page_number;           // page number in flash memory (starting at 1)
      uint8_t         flash_block_number;          // block number in flash memory (starting at 1)
  }req_t;
  </code></pre>