mbox.h 3.92 KB
/*
 * Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de>
 *
 * This file is subject to the terms and conditions of the GNU Lesser
 * General Public License v2.1. See the file LICENSE in the top level
 * directory for more details.
 */

/**
 * @defgroup    core_mbox Mailboxes
 * @ingroup     core
 * @brief       Mailbox implementation
 *
 * @{
 *
 * @file
 * @brief       Mailbox API
 *
 * @author      Kaspar Schleiser <kaspar@schleiser.de>
 */

#ifndef MBOX_H
#define MBOX_H

#include "list.h"
#include "cib.h"
#include "msg.h"

#ifdef __cplusplus
extern "C" {
#endif

/** Static initializer for mbox objects */
#define MBOX_INIT(queue, queue_size) {{0}, {0}, CIB_INIT(queue_size), queue}

/**
 * @brief Mailbox struct definition
 */
typedef struct {
    list_node_t readers;    /**< list of threads waiting for message    */
    list_node_t writers;    /**< list of threads waiting to send        */
    cib_t cib;              /**< cib for msg array                      */
    msg_t *msg_array;       /**< ptr to array of msg queue              */
} mbox_t;

enum {
    NON_BLOCKING = 0,       /**< non-blocking mode */
    BLOCKING,               /**< blocking mode */
};

/**
 * @brief Initialize mbox object
 *
 * @note The message queue size must be a power of two!
 *
 * @param[in]   mbox        ptr to mailbox to initialize
 * @param[in]   queue       array of msg_t used as queue
 * @param[in]   queue_size  number of msg_t objects in queue
 */
static inline void mbox_init(mbox_t *mbox, msg_t *queue, unsigned int queue_size)
{
    mbox_t m = MBOX_INIT(queue, queue_size);
    *mbox = m;
}

/**
 * @brief Add message to mailbox
 *
 * If the mailbox is full, this fuction will return right away.
 *
 * @internal
 *
 * @param[in] mbox      ptr to mailbox to operate on
 * @param[in] msg       ptr to message that will be copied into mailbox
 * @param[in] blocking  block if 1, don't block if 0
 *
 * @return  1   if msg could be delivered
 * @return  0   otherwise
 */
int _mbox_put(mbox_t *mbox, msg_t *msg, int blocking);

/**
 * @brief Get message from mailbox
 *
 * If the mailbox is empty, this fuction will return right away.
 *
 * @internal
 *
 * @param[in] mbox  ptr to mailbox to operate on
 * @param[in] msg   ptr to storage for retrieved message
 * @param[in] blocking  block if 1, don't block if 0
 *
 * @return  1   if msg could be retrieved
 * @return  0   otherwise
 */
int _mbox_get(mbox_t *mbox, msg_t *msg, int blocking);

/**
 * @brief Add message to mailbox
 *
 * If the mailbox is full, this fuction will block until space becomes
 * available.
 *
 * @param[in] mbox  ptr to mailbox to operate on
 * @param[in] msg   ptr to message that will be copied into mailbox
 */
static inline void mbox_put(mbox_t *mbox, msg_t *msg)
{
    _mbox_put(mbox, msg, BLOCKING);
}

/**
 * @brief Add message to mailbox
 *
 * If the mailbox is full, this fuction will return right away.
 *
 * @param[in] mbox  ptr to mailbox to operate on
 * @param[in] msg   ptr to message that will be copied into mailbox
 *
 * @return  1   if msg could be delivered
 * @return  0   otherwise
 */
static inline int mbox_try_put(mbox_t *mbox, msg_t *msg)
{
    return _mbox_put(mbox, msg, NON_BLOCKING);
}

/**
 * @brief Get message from mailbox
 *
 * If the mailbox is empty, this fuction will block until a message becomes
 * available.
 *
 * @param[in] mbox  ptr to mailbox to operate on
 * @param[in] msg   ptr to storage for retrieved message
 */
static inline void mbox_get(mbox_t *mbox, msg_t *msg)
{
    _mbox_get(mbox, msg, BLOCKING);
}

/**
 * @brief Get message from mailbox
 *
 * If the mailbox is empty, this fuction will return right away.
 *
 * @param[in] mbox  ptr to mailbox to operate on
 * @param[in] msg   ptr to storage for retrieved message
 *
 * @return  1   if msg could be retrieved
 * @return  0   otherwise
 */
static inline int mbox_try_get(mbox_t *mbox, msg_t *msg)
{
    return _mbox_get(mbox, msg, NON_BLOCKING);
}

#ifdef __cplusplus
}
#endif

/** @} */
#endif /* MBOX_H */