Dear developers

My application uses queues and I notice that I had some difficulties when
reaching the end and start of the queue. I'm using the latest (21 febr 2003)
snapshot of apr and apr-util. Platforms on which it occurs, Windows and
Linux.
To make the problem more accessible I use most of the same code as the
testqueue.c provided in the distribution. Only to simplify I use one
producer and one consumer only and a queue of size 1. The producer pushes
values 0,1,2,3,... and the consumer pops them one by one. The following
output is obtained:

        0: value 0 succesfully pushed.
        1: value 1 succesfully pushed.
                0: value 1 succesfully popped.
        2: value 2 succesfully pushed.
          1: value 2 succesfully popped.
        3: value 3 succesfully pushed.
          2: value 3 succesfully popped.
                3: value 3 succesfully popped.

You can notice a few things:
1. value 0 is never popped
2. there are two values pushed on a queue of size 1!
3. value 3 is popped twice on a queue of size 1.

I don't think I made a mistake in the code, but just for those who might
doubt that, I attached the used code.


#include "apr.h"
#include "apr_pools.h"
#include "apr_thread_proc.h"
#include "apr_queue.h"
#include "apr_time.h"

#define TESTSIZE 4 
apr_pool_t *pool;


void* APR_THREAD_FUNC producer(apr_thread_t * thread_a, void* data_a){
        int i;
        apr_status_t rv;
    apr_queue_t *q = (apr_queue_t*)data_a;
        int *val;
        
        for (i=0; i<TESTSIZE; i++){
                val = apr_pcalloc(pool, sizeof(int));
                *val = i;
                do {
                        rv = apr_queue_push(q, val);
                } while (rv == APR_EINTR);
                if (rv==APR_SUCCESS){
                        printf("%d: value %d succesfully pushed.\n", i,
*val);
                }
                rv == -1; //just to be sure we aren't checking the same rv
twice
        }
        return (NULL);
}

void* APR_THREAD_FUNC consumer(apr_thread_t * thread_a, void* data_a){
        void * v;
        int result;
    apr_queue_t *q = (apr_queue_t*)data_a;
        int i = 0;
        apr_status_t rv;

        apr_sleep(APR_USEC_PER_SEC); //just to be sure the producer is first
        while (i<TESTSIZE){
                do {
                        rv = apr_queue_pop(q,&v);
                } while (rv == APR_EINTR);
                if (rv == APR_SUCCESS){
                        result = **(int **)v;
                        printf("\t%d: value %d succesfully popped.\n", i,
result);
                        i++;
                }
                rv = -1; //just to be sure that rv is really a succes
        }
        return (NULL);
}

int
main(){
        
    apr_queue_t *q;
        apr_thread_t* prod;
        apr_thread_t* cons;
        apr_status_t prod_rv;
        apr_status_t cons_rv;
        char dummy;

        apr_initialize();
        apr_pool_create(&pool, NULL);
        /* Creating a queue of size 1 */
        apr_queue_create(&q,1,pool);
         
        /* Creating two threads, producer(prod) and consumer(cons) */
        apr_thread_create(&prod, NULL, producer, q, pool);
        apr_thread_create(&cons, NULL, consumer, q, pool);
        apr_thread_join(&prod_rv, prod);
        apr_thread_join(&cons_rv, cons);
        apr_pool_destroy(pool);
        apr_terminate();
        printf("hit <ENTER> to end...");
        scanf("%c", &dummy);
        return 0;
}

Reply via email to