/* -*- mode: c ; c-file-style: "canonware-c-style" -*-
 ****************************************************************************
 *
 * Copyright (C) 1996-1999 Jason Evans <jasone@canonware.com>.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice(s), this list of conditions and the following disclaimer as
 *    the first lines of this file unmodified other than the possible
 *    addition of one or more copyright notices.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice(s), this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************
 *
 * Version: s19990912a
 *
 * <<< Description >>>
 *
 * Public interface for the mq (message queue) class.
 *
 ****************************************************************************/

/* Pseudo-opaque type. */
typedef struct cw_mq_s cw_mq_t;

struct cw_mq_s
{
  cw_bool_t is_malloced;
#if (defined(_LIBSTASH_DBG) || defined(_LIBSTASH_DEBUG))
  cw_uint32_t magic;
#endif
#ifdef _CW_REENTRANT
  cw_mtx_t lock;
  cw_cnd_t cond;
#endif

  cw_bool_t get_stop;
  cw_bool_t put_stop;
  
  cw_ring_t * ring;
  cw_ring_t * spares_ring;
};

/****************************************************************************
 *
 * <<< Input(s) >>>
 *
 * a_mq : Pointer to space for a mq, or NULL.
 *
 * <<< Output(s) >>>
 *
 * retval : FALSE == success, TRUE == error.
 *          TRUE : Memory allocation error.  Can only occur if (NULL == a_mq).
 *
 * <<< Description >>>
 *
 * Constructor.
 *
 ****************************************************************************/
cw_mq_t *
mq_new(cw_mq_t * a_mq);

/****************************************************************************
 *
 * <<< Input(s) >>>
 *
 * a_mq : Pointer to a mq.
 *
 * <<< Output(s) >>>
 *
 * None.
 *
 * <<< Description >>>
 *
 * Destructor.
 *
 ****************************************************************************/
void
mq_delete(cw_mq_t * a_mq);

/****************************************************************************
 *
 * <<< Input(s) >>>
 *
 * a_mq : Pointer to a mq.
 *
 * <<< Output(s) >>>
 *
 * retval : Pointer to a message, or NULL.
 *          NULL : No messages in the queue, or get is in the stop state.
 *
 * <<< Description >>>
 *
 * Try to get a message, but return NULL if none are available.
 *
 ****************************************************************************/
void *
mq_tryget(cw_mq_t * a_mq);

/****************************************************************************
 *
 * <<< Input(s) >>>
 *
 * a_mq : Pointer to a mq.
 *
 * <<< Output(s) >>>
 *
 * retval : Pointer to a message, or NULL.
 *          NULL : get is in the stop state.
 *
 * <<< Description >>>
 *
 * Get a message.  If none are available, block until a message is available.
 *
 * Note: This function is only available in the threaded versions of libstash.
 *
 ****************************************************************************/
#ifdef _CW_REENTRANT
void *
mq_get(cw_mq_t * a_mq);
#endif

/****************************************************************************
 *
 * <<< Input(s) >>>
 *
 * a_mq : Pointer to a mq.
 *
 * a_message : Pointer to a message.
 *
 * <<< Output(s) >>>
 *
 * retval : -1 == Memory allocation error.
 *           0 == Success.
 *           1 == Failure due to put being in the stop state.
 *
 * <<< Description >>>
 *
 * Put a message in the queue.
 *
 ****************************************************************************/
cw_sint32_t
mq_put(cw_mq_t * a_mq, const void * a_message);

/****************************************************************************
 *
 * <<< Input(s) >>>
 *
 * a_mq : Pointer to a mq.
 *
 * <<< Output(s) >>>
 *
 * retval : FALSE == success, TRUE == error (already in start state).
 *
 * <<< Description >>>
 *
 * Change the get operation to the start state (mq_get() will not return 1).
 *
 ****************************************************************************/
cw_bool_t
mq_start_get(cw_mq_t * a_mq);

/****************************************************************************
 *
 * <<< Input(s) >>>
 *
 * a_mq : Pointer to a mq.
 *
 * <<< Output(s) >>>
 *
 * retval : FALSE == success, TRUE == error (already in stop state).
 *
 * <<< Description >>>
 *
 * Change the get operation to the stop state (mq_get() will return 1).
 *
 ****************************************************************************/
cw_bool_t
mq_stop_get(cw_mq_t * a_mq);

/****************************************************************************
 *
 * <<< Input(s) >>>
 *
 * a_mq : Pointer to a mq.
 *
 * <<< Output(s) >>>
 *
 * retval : FALSE == success, TRUE == error (already in start state).
 *
 * <<< Description >>>
 *
 * Change the put operation to the start state (mq_put() will not return 1).
 *
 ****************************************************************************/
cw_bool_t
mq_start_put(cw_mq_t * a_mq);

/****************************************************************************
 *
 * <<< Input(s) >>>
 *
 * a_mq : Pointer to a mq.
 *
 * <<< Output(s) >>>
 *
 * retval : FALSE == success, TRUE == error (already in stop state).
 *
 * <<< Description >>>
 *
 * Change the put operation to the stop state (mq_put() will return 1).
 *
 ****************************************************************************/
cw_bool_t
mq_stop_put(cw_mq_t * a_mq);
