327 lines
11 KiB
C++
327 lines
11 KiB
C++
/*************************************************************************\
|
|
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
|
* National Laboratory.
|
|
* Copyright (c) 2002 The Regents of the University of California, as
|
|
* Operator of Los Alamos National Laboratory.
|
|
* SPDX-License-Identifier: EPICS
|
|
* EPICS Base is distributed subject to a Software License Agreement found
|
|
* in file LICENSE that is included with this distribution.
|
|
\*************************************************************************/
|
|
|
|
/**
|
|
* \file epicsMessageQueue.h
|
|
* \author W. Eric Norum
|
|
*
|
|
* \brief A C++ and a C facility for communication between threads.
|
|
*
|
|
* Each C function corresponds to one of the C++ methods.
|
|
*/
|
|
|
|
#ifndef epicsMessageQueueh
|
|
#define epicsMessageQueueh
|
|
|
|
#include "epicsAssert.h"
|
|
#include "libComAPI.h"
|
|
|
|
typedef struct epicsMessageQueueOSD *epicsMessageQueueId;
|
|
|
|
#ifdef __cplusplus
|
|
|
|
/** Provides methods for sending messages between threads on a first in,
|
|
* first out basis. It is designed so that a single message queue can
|
|
* be used with multiple writer and reader threads.
|
|
*
|
|
* A C++ epicsMessageQueue cannot be assigned to, copy-constructed, or
|
|
* constructed without giving the capacity and max-imumMessageSize
|
|
* arguments.
|
|
*
|
|
* The C++ compiler will object to some of the statements below:
|
|
* \code{.cpp}
|
|
* epicsMessageQueue mq0(); // Error: default constructor is private
|
|
* epicsMessageQueue mq1(10, 20); // OK
|
|
* epicsMessageQueue mq2(t1); // Error: copy constructor is private
|
|
* epicsMessageQueue*pmq; // OK, pointer
|
|
* *pmq = mq1; // Error: assignment operator is private
|
|
* pmq = &mq1; // OK, pointer assignment and address-of
|
|
* \endcode
|
|
**/
|
|
class LIBCOM_API epicsMessageQueue {
|
|
public:
|
|
|
|
/**
|
|
* \brief Constructor.
|
|
* \param capacity Maximum number of messages to queue
|
|
* \param maximumMessageSize Number of bytes of the largest
|
|
* message that may be queued
|
|
**/
|
|
epicsMessageQueue ( unsigned int capacity,
|
|
unsigned int maximumMessageSize );
|
|
|
|
/**
|
|
* \brief Destructor.
|
|
**/
|
|
~epicsMessageQueue ();
|
|
|
|
/**
|
|
* \brief Try to send a message.
|
|
* \note On VxWorks and RTEMS this method may be called from
|
|
* an interrupt handler.
|
|
* \returns 0 if the message was sent to a receiver or queued for
|
|
* future delivery.
|
|
* \returns -1 if no more messages can be queued or if the message
|
|
* is larger than the queue's maximum message size.
|
|
**/
|
|
int trySend ( void *message, unsigned int messageSize );
|
|
|
|
/**
|
|
* \brief Send a message.
|
|
* \returns 0 if the message was sent to a receiver or queued for
|
|
* future delivery.
|
|
* \returns -1 if the message is larger than the queue's maximum
|
|
* message size.
|
|
**/
|
|
int send ( void *message, unsigned int messageSize );
|
|
|
|
/**
|
|
* \brief Send a message or timeout.
|
|
* \param message Pointer to the message to be sent
|
|
* \param messageSize The size of \p message
|
|
* \param timeout The timeout delay in seconds. A timeout of zero is
|
|
* equivalent to calling trySend(); NaN or any value too large to be
|
|
* represented to the target OS is equivalent to no timeout.
|
|
* \returns 0 if the message was sent to a receiver or queued for
|
|
* future delivery.
|
|
* \returns -1 if the timeout was reached before the
|
|
* message could be sent or queued, or if the message is larger
|
|
* than the queue's maximum message size.
|
|
**/
|
|
int send ( void *message, unsigned int messageSize, double timeout );
|
|
|
|
/**
|
|
* \brief Try to receive a message.
|
|
* \param[out] message Output buffer to store the received message
|
|
* \param size Size of the buffer pointed to by \p message
|
|
*
|
|
* If the queue holds at least one message,
|
|
* the first message on the queue is moved to the specified location
|
|
* and the length of that message is returned.
|
|
*
|
|
* If the received message is larger than the specified message size
|
|
* the implementation may either return -1, or truncate the
|
|
* message. It is most efficient if the messageBufferSize is equal
|
|
* to the maximumMessageSize with which the message queue was
|
|
* created.
|
|
* \returns Number of bytes in the message.
|
|
* \returns -1 if the message queue is empty, or the buffer too small.
|
|
**/
|
|
int tryReceive ( void *message, unsigned int size );
|
|
|
|
/**
|
|
* \brief Fetch the next message on the queue.
|
|
* \param[out] message Output buffer to store the received message
|
|
* \param size Size of the buffer pointed to by \p message
|
|
*
|
|
* Wait for a message to be sent if the queue is empty, then move
|
|
* the first message queued to the specified location.
|
|
*
|
|
* If the received message is larger than the specified message size
|
|
* the implementation may either return -1, or truncate the
|
|
* message. It is most efficient if the messageBufferSize is equal
|
|
* to the maximumMessageSize with which the message queue was
|
|
* created.
|
|
* \returns Number of bytes in the message.
|
|
* \returns -1 if the buffer is too small for the message.
|
|
**/
|
|
int receive ( void *message, unsigned int size );
|
|
|
|
/**
|
|
* \brief Wait for and fetch the next message.
|
|
* \param[out] message Output buffer to store the received message
|
|
* \param size Size of the buffer pointed to by \p message
|
|
* \param timeout The timeout delay in seconds. A timeout of zero is
|
|
* equivalent to calling tryReceive(); NaN or any value too large to
|
|
* be represented to the target OS is equivalent to no timeout.
|
|
*
|
|
* Waits up to \p timeout seconds for a message to arrive if the queue
|
|
* is empty, then moves the first message to the message buffer.
|
|
*
|
|
* If the received message is larger than the buffer size
|
|
* the implementation may either return -1, or truncate the
|
|
* message. It is most efficient if the messageBufferSize is equal
|
|
* to the maximumMessageSize with which the message queue was
|
|
* created.
|
|
* \returns Number of bytes in the message.
|
|
* \returns -1 if a message is not received within the timeout
|
|
* interval.
|
|
**/
|
|
int receive ( void *message, unsigned int size, double timeout );
|
|
|
|
/**
|
|
* \brief Displays some information about the message queue.
|
|
* \param level Controls the amount of information displayed.
|
|
**/
|
|
void show ( unsigned int level = 0 );
|
|
|
|
/**
|
|
* \brief How many messages are queued.
|
|
* \returns The number of messages presently in the queue.
|
|
**/
|
|
unsigned int pending ();
|
|
|
|
private:
|
|
/**
|
|
* Prevent compiler-generated member functions default constructor,
|
|
* copy constructor, assignment operator.
|
|
**/
|
|
epicsMessageQueue();
|
|
epicsMessageQueue(const epicsMessageQueue &);
|
|
epicsMessageQueue& operator=(const epicsMessageQueue &);
|
|
|
|
epicsMessageQueueId id;
|
|
};
|
|
|
|
extern "C" {
|
|
#endif /*__cplusplus */
|
|
|
|
/**
|
|
* \brief Create a message queue.
|
|
* \param capacity Maximum number of messages to queue
|
|
* \param maximumMessageSize Number of bytes of the largest
|
|
* message that may be queued
|
|
* \return An identifier for the new queue, or 0.
|
|
**/
|
|
LIBCOM_API epicsMessageQueueId epicsStdCall epicsMessageQueueCreate(
|
|
unsigned int capacity,
|
|
unsigned int maximumMessageSize);
|
|
|
|
/**
|
|
* \brief Destroy a message queue, release all its memory.
|
|
**/
|
|
LIBCOM_API void epicsStdCall epicsMessageQueueDestroy(
|
|
epicsMessageQueueId id);
|
|
|
|
/**
|
|
* \brief Try to send a message.
|
|
* \note On VxWorks and RTEMS this routine may be called from
|
|
* an interrupt handler.
|
|
* \returns 0 if the message was sent to a receiver or queued for
|
|
* future delivery.
|
|
* \returns -1 if no more messages can be queued or if the message
|
|
* is larger than the queue's maximum message size.
|
|
**/
|
|
LIBCOM_API int epicsStdCall epicsMessageQueueTrySend(
|
|
epicsMessageQueueId id,
|
|
void *message,
|
|
unsigned int messageSize);
|
|
|
|
/**
|
|
* \brief Send a message.
|
|
* \returns 0 if the message was sent to a receiver or queued for
|
|
* future delivery.
|
|
* \returns -1 if the message is larger than the queue's maximum
|
|
* message size.
|
|
**/
|
|
LIBCOM_API int epicsStdCall epicsMessageQueueSend(
|
|
epicsMessageQueueId id,
|
|
void *message,
|
|
unsigned int messageSize);
|
|
|
|
/**
|
|
* \brief Send a message or timeout.
|
|
* \returns 0 if the message was sent to a receiver or queued for
|
|
* future delivery.
|
|
* \returns -1 if the timeout was reached before the
|
|
* message could be sent or queued, or if the message is larger
|
|
* than the queue's maximum message size.
|
|
**/
|
|
LIBCOM_API int epicsStdCall epicsMessageQueueSendWithTimeout(
|
|
epicsMessageQueueId id,
|
|
void *message,
|
|
unsigned int messageSize,
|
|
double timeout);
|
|
|
|
/**
|
|
* \brief Try to receive a message.
|
|
*
|
|
* If the queue holds at least one message,
|
|
* the first message on the queue is moved to the specified location
|
|
* and the length of that message is returned.
|
|
*
|
|
* If the received message is larger than the specified message size
|
|
* the implementation may either return -1, or truncate the
|
|
* message. It is most efficient if the messageBufferSize is equal
|
|
* to the maximumMessageSize with which the message queue was
|
|
* created.
|
|
* \returns Number of bytes in the message.
|
|
* \returns -1 if the message queue is empty, or the buffer too small.
|
|
**/
|
|
LIBCOM_API int epicsStdCall epicsMessageQueueTryReceive(
|
|
epicsMessageQueueId id,
|
|
void *message,
|
|
unsigned int size);
|
|
|
|
/**
|
|
* \brief Fetch the next message on the queue.
|
|
*
|
|
* Wait for a message to be sent if the queue is empty, then move the
|
|
* first message queued to the specified location.
|
|
*
|
|
* If the received message is larger than the specified message size
|
|
* the implementation may either return -1, or truncate the
|
|
* message. It is most efficient if the messageBufferSize is equal
|
|
* to the maximumMessageSize with which the message queue was
|
|
* created.
|
|
* \returns Number of bytes in the message.
|
|
* \returns -1 if the buffer is too small for the message.
|
|
**/
|
|
LIBCOM_API int epicsStdCall epicsMessageQueueReceive(
|
|
epicsMessageQueueId id,
|
|
void *message,
|
|
unsigned int size);
|
|
|
|
/**
|
|
* \brief Wait for a message to be queued.
|
|
*
|
|
* Wait up to \p timeout seconds for a message to be sent if the queue
|
|
* is empty, then move the first message to the specified location.
|
|
*
|
|
* If the received message is larger than the specified message buffer
|
|
* size the implementation may either return -1, or truncate the
|
|
* message. It is most efficient if the messageBufferSize is equal
|
|
* to the maximumMessageSize with which the message queue was
|
|
* created.
|
|
* \returns Number of bytes in the message.
|
|
* \returns -1 if a message is not received within the timeout
|
|
* interval.
|
|
**/
|
|
LIBCOM_API int epicsStdCall epicsMessageQueueReceiveWithTimeout(
|
|
epicsMessageQueueId id,
|
|
void *message,
|
|
unsigned int size,
|
|
double timeout);
|
|
|
|
/**
|
|
* \brief How many messages are queued.
|
|
* \param id Message queue identifier.
|
|
* \returns The number of messages presently in the queue.
|
|
**/
|
|
LIBCOM_API int epicsStdCall epicsMessageQueuePending(
|
|
epicsMessageQueueId id);
|
|
|
|
/**
|
|
* \brief Displays some information about the message queue.
|
|
* \param id Message queue identifier.
|
|
* \param level Controls the amount of information displayed.
|
|
**/
|
|
LIBCOM_API void epicsStdCall epicsMessageQueueShow(
|
|
epicsMessageQueueId id,
|
|
int level);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
|
|
#include "osdMessageQueue.h"
|
|
|
|
#endif /* epicsMessageQueueh */
|