

/**
 * @brief Структура дескриптора очереди  
 
typedef struct {
    uintptr_t id;       ///< PID или указатель на очередь 
    char *name;         ///< Имя очереди (для реализаций, где оно присутствует)
} hsal_mqueue_desc;*/
TYPE hsal_mqueue_desc:
STRUCT 
    id: uintptr_t;
	name: REF_TO BYTE; 
END_STRUCT
END_TYPE

(*
/**
 * @brief Общий интерфейс очереди 
 */
typedef struct HSAL_MQueue {
    hsal_mqueue_desc desc;      ///< Дескриптор очереди 
    HSAL_CondVar condvar;       ///< Для оповещения потребителя данных 
    HSAL_Mutex mtx;             ///< Мютекс для доступа к очереди
    size_t max_items;           ///< Максимальное количество элементов в очереди
    void *ext;                  ///< Данные для расширения в "наследниках"
    int ( *destr)(void * );       ///< Коллбек-деструктор элемента очереди 

    /**
     * @brief Инициализация очереди сообщений
     * @param [in] max_items Максимальное количество элементов в очереди
     * @param [in] args Структура с параметрами инициализациями
     * @param [in] destr Указатель на коллбек-деструктор элемента очереди (или NULL если не нужен)
     * @return Код ошибки 
     */
    int ( *init)(size_t max_items, void *args, int ( *destr)(void * ));
    /**
     * @brief Помещение сообщения в очередь 
     * @param [in] queue Описатель очереди 
     * @param [in] msg Данные-сообщение
     * @param [in] size Длина сообщения
     * @param [in] timeout Таймаут на помещение в очередь, в случае если прямо сейчас не доступна
     * @return Код ошибки 
     */
    int ( *push)(struct HSAL_MQueue *queue, const void *msg, size_t size, uint32_t timeout);
    /**
     * @brief Извлечение сообщения из очереди с удалением
     * @param [in] queue Описатель очереди 
     * @param [out] msg Буфер для копирования сообщения, или NULL если нужно просто удалить без копирования
     * @param [in] timeout Таймаут на помещение в очередь, в случае если прямо сейчас не доступна
     * @return Код ошибки или 0 в случае успеха
     */
    int ( *pop)(struct HSAL_MQueue *queue, void *msg, uint32_t timeout);
    /**
     * @brief Извлечение сообщения из очереди без удаления
     * @param [in] queue Описатель очереди  
     * @param [in] timeout Таймаут на помещение в очередь, в случае если прямо сейчас не доступна
     * @return Код ошибки или 0 в случае успеха
     * @note В случае ошибки msg будет равен NULL
     */
    void* ( *peek)(struct HSAL_MQueue *queue, uint32_t timeout);
    /**
     * @brief Получить текущее количество сообщений в очереди 
     * @param [in] queue Описатель очереди 
     * @return > 0 - валидный текущий размер очереди, 0 - очередь пустая, < 0 код ошибки
     */
    int ( *size)(struct HSAL_MQueue *queue);
    /**
     * @brief Проверка, пустая ли очередь 
     * @param [in] queue Описатель очереди 
     * @return 1 - очередь не пустая, 0 - очередь пустая, < 0 код ошибки
     */
    int ( *is_empty)(struct HSAL_MQueue *queue);
    /**
     * @brief Проверка, заполнена ли очередь 
     * @param [in] queue Описатель очереди 
     * @return 1 - очередь заполнена, 0 - в очереди есть свободное место, < 0 код ошибки
     */
    int ( *is_full)(struct HSAL_MQueue *queue);
    /**
     * @brief Ожидать появления новых данных в очереди (по сути, оповещение треда-приемника)
     * @param [in] queue Описатель очереди 
     * @return 0 - успех, < 0 код ошибки
     */
    int ( *wait_data)(struct HSAL_MQueue *queue);
    /**
     * @brief Деинициализация очереди сообщений
     * @param [in] queue Описатель очереди 
     * @return Код ошибки 
     */
    int ( *deinit)(struct HSAL_MQueue *queue);
} HSAL_MQueue;

*)

@EXTERNAL FUNCTION typedef_HSAL_MQueue_destr : DINT
VAR_INPUT 
	val:REF_TO VOID;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_MQueue_init : DINT
VAR_INPUT 
	max_items:DWORD;
    args :REF_TO VOID;
    destr:REF_TO typedef_HSAL_MQueue_destr;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_MQueue_push : DINT
VAR_INPUT 
	queue:REF_TO HSAL_MQueue;
    msg: REF_TO VOID;
    size: DWORD;
    timeout: DWORD;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_MQueue_pop : DINT
VAR_INPUT 
	queue:REF_TO HSAL_MQueue;
    msg: REF_TO VOID;
    timeout: DWORD;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_MQueue_peek : REF_TO VOID
VAR_INPUT 
	queue:REF_TO HSAL_MQueue;
    timeout: DWORD;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_MQueue_size : DINT
VAR_INPUT 
	queue:REF_TO HSAL_MQueue;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_MQueue_is_empty : DINT
VAR_INPUT 
	queue:REF_TO HSAL_MQueue;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_MQueue_is_full : DINT
VAR_INPUT 
	queue:REF_TO HSAL_MQueue;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_MQueue_wait_data : DINT
VAR_INPUT 
	queue:REF_TO HSAL_MQueue;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_MQueue_deinit : DINT
VAR_INPUT 
	queue:REF_TO HSAL_MQueue;
END_VAR
END_FUNCTION


TYPE HSAL_MQueue:
STRUCT 
    desc    :hsal_mqueue_desc;      ///< Дескриптор очереди 
    condvar :HSAL_CondVar;       ///< Для оповещения потребителя данных 
    mtx     :HSAL_Mutex;             ///< Мютекс для доступа к очереди
    max_items:size_t;           ///< Максимальное количество элементов в очереди
    ext     :REF_TO VOID;                  ///< Данные для расширения в "наследниках"	create : REF_TO typedef_HSAL_MQueue_create; 
    destr   :REF_TO typedef_HSAL_MQueue_destr;
    init    :REF_TO typedef_HSAL_MQueue_init;
    push    :REF_TO typedef_HSAL_MQueue_push;
    pop     :REF_TO typedef_HSAL_MQueue_pop;
    peek    :REF_TO typedef_HSAL_MQueue_peek;
    size    :REF_TO typedef_HSAL_MQueue_size;
    is_empty   :REF_TO typedef_HSAL_MQueue_is_empty;
    is_full    :REF_TO typedef_HSAL_MQueue_is_full;
    wait_data  :REF_TO typedef_HSAL_MQueue_wait_data;
    deinit     :REF_TO typedef_HSAL_MQueue_deinit;
END_STRUCT
END_TYPE

(*
/**
 * @brief Структура-интерфейс для создания и уничтожения очередей 
 */
typedef struct { 
    /**
     * @brief Конструктор очереди сообщений
     * @param [in] q Заранее созданная очередь для инициализации  
     * @param [in] max_items Максимальный размер очереди
     * @param [in] destr Указатель на коллбек-деструктор элемента очереди (или NULL если не нужен) 
     * @return 0 в случае успеха, или код ошибки
     */
    int ( *create)(HSAL_MQueue *q, int max_items, int ( *destr)(void * ));    
    /**
     * @brief Деструктор очереди сообщений
     * @param [in] q Описатель очереди 
     * @return Код ошибки или 0 в случае успеха
     */
    int ( *destroy)(struct HSAL_MQueue* q);
} HSAL_MQueue_If;*)

@EXTERNAL FUNCTION typedef_HSAL_MQueue_create : DINT
VAR_INPUT 
	q:REF_TO HSAL_MQueue;
    max_items:DINT;
    destr:REF_TO typedef_HSAL_MQueue_destroy;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_MQueue_destroy: DINT
VAR_INPUT 
	q:REF_TO HSAL_MQueue;
END_VAR
END_FUNCTION


TYPE HSAL_MQueue_If:
STRUCT 
	create : REF_TO typedef_HSAL_MQueue_create; 
    destroy: REF_TO typedef_HSAL_MQueue_destroy;
END_STRUCT
END_TYPE

/**
 * @brief Глобальный объект, конструирующий и удаляющий очереди
 */
 //extern HSAL_MQueue_If MQueueIf; 
 @EXTERNAL VAR_GLOBAL 
    MQueueIf : HSAL_MQueue_If; 
END_VAR




/* ИНТЕРФЕЙСЫ ОЧЕРЕДЕЙ В LINUX, SEGGER EMBOS, ZEPHYR RTOS */

//#include <mqueue.h>

// struct mq_attr {
//     long mq_flags; /* Message queue description flags: 0 or
//     O_NONBLOCK [mq_getattr(), mq_setattr()] */
//     long mq_maxmsg; /* Maximum number of messages on queue
//     [mq_open(), mq_getattr()] */
//     long mq_msgsize; /* Maximum message size (in bytes)
//     [mq_open(), mq_getattr()] */
//     long mq_curmsgs; /* Number of messages currently in queue
//     [mq_getattr()] */
// };
/*
Linux

mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr);
int mq_close(mqd_t mqdes);
int mq_getattr(mqd_t mqdes, struct mq_attr *attr);
int mq_setattr(mqd_t mqdes, const struct mq_attr *newattr, struct mq_attr *oldattr);
int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio);
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);
int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout);
ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct timespec *abs_timeout);
int mq_notify(mqd_t mqdes, const struct sigevent *notification);
int mq_unlink(const char *name);

EmbOS

void OS_QUEUE_Clear(OS_QUEUE* pQ);
void OS_QUEUE_Create(OS_QUEUE* pQ, void* pData, OS_UINT Size);
void OS_QUEUE_Delete(OS_QUEUE* pQ);
int OS_QUEUE_GetMessageCnt(OS_CONST_PTR OS_QUEUE *pQ);
int OS_QUEUE_GetMessageSize(OS_CONST_PTR OS_QUEUE *pQ);
int OS_QUEUE_GetPtr(OS_QUEUE* pQ, void** ppData);
int OS_QUEUE_GetPtrBlocked(OS_QUEUE* pQ, void** ppData);
int OS_QUEUE_GetPtrTimed(OS_QUEUE* pQ, void** ppData, OS_TIME Timeout);
OS_BOOL OS_QUEUE_IsInUse(OS_CONST_PTR OS_QUEUE *pQ);
int OS_QUEUE_PeekPtr(OS_CONST_PTR OS_QUEUE *pQ, void** ppData);
void OS_QUEUE_Purge(OS_QUEUE* pQ);
int OS_QUEUE_Put(OS_QUEUE* pQ, OS_CONST_PTR void *pSrc, OS_UINT Size);
int OS_QUEUE_PutEx(OS_QUEUE* pQ,OS_CONST_PTR OS_QUEUE_SRCLIST *pSrcList, OS_UINT NumSrc);
void OS_QUEUE_PutBlocked(OS_QUEUE* pQ, OS_CONST_PTR void *pSrc, OS_UINT Size);
void OS_QUEUE_PutBlockedEx(OS_QUEUE* pQ, OS_CONST_PTR OS_QUEUE_SRCLIST *pSrcList, OS_UINT NumSrc);
char OS_QUEUE_PutTimed(OS_QUEUE* pQ, OS_CONST_PTR void *pSrc, OS_UINT Size, OS_TIME Timeout);
char OS_QUEUE_PutTimedEx(OS_QUEUE* pQ, OS_CONST_PTR OS_QUEUE_SRCLIST *pSrcList, OS_UINT NumSrc, OS_TIME Timeout);

Zephyr

void k_msgq_init(struct k_msgq *msgq, char *buffer, size_t msg_size, uint32_t max_msgs);
int k_msgq_alloc_init(struct k_msgq *msgq, size_t msg_size, uint32_t max_msgs);
int k_msgq_cleanup(struct k_msgq *msgq);
int k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout);
int k_msgq_get(struct k_msgq *msgq, void *data, k_timeout_t timeout);
int k_msgq_peek(struct k_msgq *msgq, void *data);
int k_msgq_peek_at(struct k_msgq *msgq, void *data, uint32_t idx);
void k_msgq_purge(struct k_msgq *msgq);
uint32_t k_msgq_num_free_get(struct k_msgq *msgq);
void k_msgq_get_attrs(struct k_msgq *msgq, struct k_msgq_attrs *attrs);
uint32_t k_msgq_num_used_get(struct k_msgq *msgq);
*/
