Blob Blame History Raw
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
 * See COPYRIGHT in top-level directory.
 */

#ifndef _ZM_QUEUE_H
#define _ZM_QUEUE_H

#define ZM_RUNTIMEQUEUE_IF 0
#define ZM_GLQUEUE_IF      1
#define ZM_MSQUEUE_IF      2
#define ZM_SWPQUEUE_IF     3
#define ZM_FAQUEUE_IF      4
#define ZM_MPBQUEUE_IF     5

extern int zm_queue_if;

int zm_queue_parse_name(const char *name);

/* default queue interface, given by configure */
#if !defined(ZM_QUEUE_CONF)
#define ZM_QUEUE_CONF @ZM_QUEUE_CONF@
#endif

/* ZM_QUEUE_IF: used in the library code to determine which queue implementation to use.
 * It is mapped to a constant if a user chooses a particular queue, or mapped to zm_queue_if
 * (variable) if a user chooses `runtime` at configure time.
 * If it is mapped to a constant (configure-time selection), a reasonable compiler can
 * easily eliminate branches, so there won't be performance penalty due to queue selection. */
#if ZM_QUEUE_CONF == ZM_RUNTIMEQUEUE_IF
#  define ZM_QUEUE_IF      zm_queue_if
#else
#  define ZM_QUEUE_IF      ZM_QUEUE_CONF
#endif /* ZM_QUEUE_CONF == ZM_RUNTIMEQUEUE_IF */

/* Generic implementation of the queue interface */

#include <assert.h>

#include <queue/zm_glqueue.h>
#include <queue/zm_msqueue.h>
#include <queue/zm_swpqueue.h>
#include <queue/zm_faqueue.h>

static inline int zm_queue_init(zm_queue_t *q)
{
    if (ZM_QUEUE_CONF == ZM_RUNTIMEQUEUE_IF) {
        const char *env_str = getenv("ZM_QUEUE_IF");
        if (env_str == NULL) {
            /* Fall back to default */
            zm_queue_if = ZM_GLQUEUE_IF;
        } else {
            zm_queue_if = zm_queue_parse_name(env_str);
        }
    }

    switch (ZM_QUEUE_IF) {
        case ZM_GLQUEUE_IF:
            return zm_glqueue_init(&q->glqueue);

        case ZM_MSQUEUE_IF:
            return zm_msqueue_init(&q->msqueue);

        case ZM_SWPQUEUE_IF:
            return zm_swpqueue_init(&q->swpqueue);

        case ZM_FAQUEUE_IF:
            return zm_faqueue_init(&q->faqueue);

        default:
            fprintf(stderr, "izem: Unknown queue interface specified. Falling back to glqueue.\n");
            zm_queue_if = ZM_GLQUEUE_IF;
            return zm_glqueue_init(&q->glqueue);
    }
}

static inline int zm_queue_enqueue(zm_queue_t* q, void *data)
{
    switch (ZM_QUEUE_IF) {
        case ZM_GLQUEUE_IF:
            return zm_glqueue_enqueue(&q->glqueue, data);

        case ZM_MSQUEUE_IF:
            return zm_msqueue_enqueue(&q->msqueue, data);

        case ZM_SWPQUEUE_IF:
            return zm_swpqueue_enqueue(&q->swpqueue, data);

        case ZM_FAQUEUE_IF:
            return zm_faqueue_enqueue(&q->faqueue, data);

        default:
            assert(0);
            return 0;
    }
}

static inline int zm_queue_dequeue(zm_queue_t* q, void **data)
{
    switch (ZM_QUEUE_IF) {
        case ZM_GLQUEUE_IF:
            return zm_glqueue_dequeue(&q->glqueue, data);

        case ZM_MSQUEUE_IF:
            return zm_msqueue_dequeue(&q->msqueue, data);

        case ZM_SWPQUEUE_IF:
            return zm_swpqueue_dequeue(&q->swpqueue, data);

        case ZM_FAQUEUE_IF:
            return zm_faqueue_dequeue(&q->faqueue, data);

        default:
            assert(0);
            return 0;
    }
}

#endif /* #ifndef_ZM_QUEUE_H */