Queue in array C through array

I implemented a queue in C using an array of structures.

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->p_head = p_cb->buffer;
    p_cb->p_tail = p_cb->buffer;
    p_cb->count = 0;
    p_cb->size = BUFFER_SIZE;

}

The problem is that the above implementation is only applicable for storing instances of req_t structures. Now I need to store instances of another and I don’t know how to define a queue in a more general way, so that I can use the same queue for instances of different structures. The problem is that I need to know the type of structure before defining the buffer. Does anyone have any ideas how to solve this?

    #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->p_head = p_cb->buffer;                                               \
      p_cb->p_tail = p_cb->buffer;                                               \
      p_cb->count = 0;                                                           \
      p_cb->size = BUFFER_SIZE;                                                  \
  }                                                                            \
                                                                               \
  // queue enqueue function definition                                         \                                                                               
  BOOL enqueue_cb_##TYPE(circular_buffer_##TYPE##_t *p_cb, TYPE *p_enq_elem){  \
                                                                               \    
    if(p_cb->count < p_cb->size){                                              \
                                                                               \
         taskENTER_CRITICAL();                                                     \
                                                                               \
            *(p_cb->p_tail) = *p_enq_elem;                                           \
            p_cb->p_tail = ((++(p_cb->p_tail) == (p_cb->buffer + p_cb->size)) ?      \
                      (p_cb->buffer) : (p_cb->p_tail));                        \
            p_cb->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->count) != 0){                                                    \
                                                                               \
        taskENTER_CRITICAL();                                                      \
                                                                               \
            *p_deq_elem = *(p_cb->p_head);                                           \
            p_cb->p_head = ((++(p_cb->p_head) == (p_cb->buffer + p_cb->size)) ?      \
                      (p_cb->buffer) : (p_cb->p_head));                        \
            p_cb->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

Structures I'm going to use with a queue

    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;

and

 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;
+4
source share
4 answers

, . , . :

req_t req_t1, :

typedef struct _req_t1
    {
    int type;
    // append the members of your first structure here
    }
req_t1;

, , req_t2:

typedef struct _req_t2
    {
    int type;
    // append the members of your second structure here
    }
req_t2;

req_t , , , , :

typedef union _req_t
    {
    int    type;
    req_t1 item1;
    req_t2 item2;
    }
req_t;

, . req_t , .

typedef struct _circular_buffer_t
    {
    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;

, p_head- > , . req_t1, p_head- > item1 req_t1, p_head- > item2 req_t2. .

+1

, void * .

typedef struct{
    void      *buffer[BUFFER_SIZE];   // buffer
    uint16_t  size;                          // length of the queue
    uint16_t  count;                 // number of elements present in the queue
    void      *p_head;                 // pointer to head of the queue (read end)
    void      *p_tail;                 // pointer to tail of the queue (write end)
}circular_buffer_t;

:

circular_buffer_t p_cb;
my_struct_t       *my_struct = malloc(sizeof(my_struct_t));

// set
p_cb.buffer[0] = (void*)my_struct;

// get
(my_struct_t*)p_cb.buffer[0];
+6

1.

, ( ) .

typedef struct {
    u32 capacity;
    u32 element_size;
    u8 * head;    // next free slot 
    u8 * tail;    // oldest enqueued item
    u8 * buffer;
    u8 * buffer_end;
} circular_buffer_t;

void circbuff_init(circular_buffer_t *p_cb, u8 *buffer, u32 element_size, u32 capacity)
{
    p_cb->capacity = capacity;
    p_cb->element_size = element_size;
    p_cb->buffer = buffer;
    p_cb->buffer_end = buffer + (capacity * element_size);
    p_cb->head = buffer;
    p_cb->tail = buffer;
}

, .count , , / ( , ).

, element_size:

circbuff_init(p_cb, buffer, sizeof(SomeStruct), sizeof(buffer) / sizeof(SomeStruct));

:

bool circbuff_dequeue(circular_buffer_t *hnd, void *dst)
{
    // if empty, do nothing
    if (circbuff_isEmpty(hnd))
        return false;

    memcpy(dst, hnd->tail, hnd->element_size);
    hnd->tail = modulo_increment(hnd, hnd->tail);
    return true;
}

2.

.

3.

, klib. , ( ), .

+3

What you want is actually a structure with a common type. C language does not support this. The best you can do to try to imitate this behavior. One way to do this is to use macros or use generic pointers. Look here to learn more about this: Pseudo-Generics in C

+2
source

Source: https://habr.com/ru/post/1685299/


All Articles