예제 #1
0
/**
 * Push new data onto the queue. Blocks if the queue is full. Once
 * the push operation has completed, it signals other threads waiting
 * in apr_queue_pop() that they may continue consuming sockets.
 * @param timeout added by Cisco. now uses apr_thread_cond_timewait(). 
 * interval of time to wait. zero means forever, negative indicates no wait, 
 * otherwise wait time in *microseconds*.
 * @return APR_SUCCESS, APR_EAGAIN, APR_EOF, APR_EINTR, APR_TIMEUP, 
 * or some APR error
 */
apr_status_t etch_apr_queue_push(etch_apr_queue_t *queue, 
                                 apr_interval_time_t timeout, 
                                 void *data)
{
    apr_status_t rv;

    if (queue->terminated)  
        rv = APR_EOF; /* no more elements ever again */
    else
    if (APR_SUCCESS == (rv = apr_thread_mutex_lock(queue->one_big_mutex)))
    {
        do 
        {   if (etch_apr_queue_full(queue)) 
            {
                if (!queue->terminated) 
                {
                    if (-1 == timeout) 
                    {   rv = APR_EAGAIN; /* asked to not wait */
                        break;
                    }

                    queue->full_waiters++;

                    if (0 == timeout)
                        rv = apr_thread_cond_wait(queue->not_full, queue->one_big_mutex);
                    else
                        rv = apr_thread_cond_timedwait(queue->not_full, queue->one_big_mutex, timeout);

                    queue->full_waiters--;
                    if (rv != APR_SUCCESS)  
                        break;
                }

                /* If we wake up and it's still empty, then we were interrupted */
                if (etch_apr_queue_full(queue)) 
                {
                    Q_DBG("queue full (intr)", queue);
                    rv = queue->terminated? APR_EOF: APR_EINTR; 
                    break;
                }
            }

            queue->data[queue->in] = data;
            queue->in = (queue->in + 1) % queue->bounds;
            queue->nelts++;

            if (queue->empty_waiters) 
            {
                Q_DBG("sig !empty", queue);
                rv = apr_thread_cond_signal(queue->not_empty);
            }

        } while(0);

        apr_thread_mutex_unlock(queue->one_big_mutex);
    }

    return rv;
}
예제 #2
0
/**
 * Retrieves the next item from the queue. If there are no
 * items available, it will block until one becomes available.
 * Once retrieved, the item is placed into the address specified by
 * 'data'.
 */
APU_DECLARE(apr_status_t) apr_queue_pop(apr_queue_t *queue, void **data)
{
    apr_status_t rv;

    if (queue->terminated) {
        return APR_EOF; /* no more elements ever again */
    }

    rv = apr_thread_mutex_lock(queue->one_big_mutex);
    if (rv != APR_SUCCESS) {
        return rv;
    }

    /* Keep waiting until we wake up and find that the queue is not empty. */
    if (apr_queue_empty(queue)) {
        if (!queue->terminated) {
            queue->empty_waiters++;
            rv = apr_thread_cond_wait(queue->not_empty, queue->one_big_mutex);
            queue->empty_waiters--;
            if (rv != APR_SUCCESS) {
                apr_thread_mutex_unlock(queue->one_big_mutex);
                return rv;
            }
        }
        /* If we wake up and it's still empty, then we were interrupted */
        if (apr_queue_empty(queue)) {
            Q_DBG("queue empty (intr)", queue);
            rv = apr_thread_mutex_unlock(queue->one_big_mutex);
            if (rv != APR_SUCCESS) {
                return rv;
            }
            if (queue->terminated) {
                return APR_EOF; /* no more elements ever again */
            }
            else {
                return APR_EINTR;
            }
        }
    } 

    *data = queue->data[queue->out];
    queue->nelts--;

    queue->out = (queue->out + 1) % queue->bounds;
    if (queue->full_waiters) {
        Q_DBG("signal !full", queue);
        rv = apr_thread_cond_signal(queue->not_full);
        if (rv != APR_SUCCESS) {
            apr_thread_mutex_unlock(queue->one_big_mutex);
            return rv;
        }
    }

    rv = apr_thread_mutex_unlock(queue->one_big_mutex);
    return rv;
}
예제 #3
0
/**
 * Push new data onto the queue. Blocks if the queue is full. Once
 * the push operation has completed, it signals other threads waiting
 * in apr_queue_pop() that they may continue consuming sockets.
 */
APU_DECLARE(apr_status_t) apr_queue_push(apr_queue_t *queue, void *data)
{
    apr_status_t rv;

    if (queue->terminated) {
        return APR_EOF; /* no more elements ever again */
    }

    rv = apr_thread_mutex_lock(queue->one_big_mutex);
    if (rv != APR_SUCCESS) {
        return rv;
    }

    if (apr_queue_full(queue)) {
        if (!queue->terminated) {
            queue->full_waiters++;
            rv = apr_thread_cond_wait(queue->not_full, queue->one_big_mutex);
            queue->full_waiters--;
            if (rv != APR_SUCCESS) {
                apr_thread_mutex_unlock(queue->one_big_mutex);
                return rv;
            }
        }
        /* If we wake up and it's still empty, then we were interrupted */
        if (apr_queue_full(queue)) {
            Q_DBG("queue full (intr)", queue);
            rv = apr_thread_mutex_unlock(queue->one_big_mutex);
            if (rv != APR_SUCCESS) {
                return rv;
            }
            if (queue->terminated) {
                return APR_EOF; /* no more elements ever again */
            }
            else {
                return APR_EINTR;
            }
        }
    }

    queue->data[queue->in] = data;
    queue->in = (queue->in + 1) % queue->bounds;
    queue->nelts++;

    if (queue->empty_waiters) {
        Q_DBG("sig !empty", queue);
        rv = apr_thread_cond_signal(queue->not_empty);
        if (rv != APR_SUCCESS) {
            apr_thread_mutex_unlock(queue->one_big_mutex);
            return rv;
        }
    }

    rv = apr_thread_mutex_unlock(queue->one_big_mutex);
    return rv;
}
예제 #4
0
/**
 * Retrieves the next item from the queue. If there are no
 * items available, it will block until one becomes available.
 * Once retrieved, the item is placed into the address specified by
 * 'data'.
 */
APU_DECLARE(apr_status_t) apr_queue_trypop(apr_queue_t *queue, void **data)
{
    apr_status_t rv;

    if (queue->terminated) {
        return APR_EOF; /* no more elements ever again */
    }

    rv = apr_thread_mutex_lock(queue->one_big_mutex);
    if (rv != APR_SUCCESS) {
        return rv;
    }

    /* Keep waiting until we wake up and find that the queue is not empty. */
    if (apr_queue_empty(queue)) {
        rv = apr_thread_mutex_unlock(queue->one_big_mutex);
        return APR_EAGAIN;
    } 

    *data = queue->data[queue->out];
    queue->nelts--;

    queue->out = (queue->out + 1) % queue->bounds;
    if (queue->full_waiters) {
        Q_DBG("signal !full", queue);
        rv = apr_thread_cond_signal(queue->not_full);
        if (rv != APR_SUCCESS) {
            apr_thread_mutex_unlock(queue->one_big_mutex);
            return rv;
        }
    }

    rv = apr_thread_mutex_unlock(queue->one_big_mutex);
    return rv;
}
예제 #5
0
/**
 * Push new data onto the queue. Blocks if the queue is full. Once
 * the push operation has completed, it signals other threads waiting
 * in apr_queue_pop() that they may continue consuming sockets.
 */
APU_DECLARE(apr_status_t) apr_queue_trypush(apr_queue_t *queue, void *data)
{
    apr_status_t rv;

    if (queue->terminated) {
        return APR_EOF; /* no more elements ever again */
    }

    rv = apr_thread_mutex_lock(queue->one_big_mutex);
    if (rv != APR_SUCCESS) {
        return rv;
    }

    if (apr_queue_full(queue)) {
        rv = apr_thread_mutex_unlock(queue->one_big_mutex);
        return APR_EAGAIN;
    }
    
    queue->data[queue->in] = data;
    queue->in = (queue->in + 1) % queue->bounds;
    queue->nelts++;

    if (queue->empty_waiters) {
        Q_DBG("sig !empty", queue);
        rv  = apr_thread_cond_signal(queue->not_empty);
        if (rv != APR_SUCCESS) {
            apr_thread_mutex_unlock(queue->one_big_mutex);
            return rv;
        }
    }

    rv = apr_thread_mutex_unlock(queue->one_big_mutex);
    return rv;
}
예제 #6
0
/**
 * Retrieves the next item from the queue. If there are no
 * items available, return APR_EAGAIN.  Once retrieved,
 * the item is placed into the address specified by 'data'.
 */
apr_status_t etch_apr_queue_trypop(etch_apr_queue_t *queue, void **data)
{
    apr_status_t rv;

    if (queue->terminated)  
        rv = APR_EOF; /* no more elements ever again */
    else
    if (APR_SUCCESS == (rv = apr_thread_mutex_lock(queue->one_big_mutex)))
    {
        if (etch_apr_queue_empty(queue)) 
            rv = APR_EAGAIN;
        else
        {   *data = queue->data[queue->out];
            queue->nelts--;

            queue->out = (queue->out + 1) % queue->bounds;

            if (queue->full_waiters) 
            {
                Q_DBG("signal !full", queue);
                rv = apr_thread_cond_signal(queue->not_full);
            }
       }

       apr_thread_mutex_unlock(queue->one_big_mutex);
    }

    return rv;
}
예제 #7
0
/**
 * Push new data onto the queue. Blocks if the queue is full. Once
 * the push operation has completed, it signals other threads waiting
 * in apr_queue_pop() that they may continue consuming sockets.
 */
apr_status_t etch_apr_queue_trypush(etch_apr_queue_t *queue, void *data)
{
    apr_status_t rv;

    if (queue->terminated)  
        rv = APR_EOF;  
    else
    if (APR_SUCCESS == (rv = apr_thread_mutex_lock(queue->one_big_mutex)))
    {
        if (etch_apr_queue_full(queue))
            rv = APR_EAGAIN;  
        else
        {   queue->data[queue->in] = data;
            queue->in = (queue->in + 1) % queue->bounds;
            queue->nelts++;

            if (queue->empty_waiters) 
            {
                Q_DBG("sig !empty", queue);
                rv  = apr_thread_cond_signal(queue->not_empty);               
            }
       }

       apr_thread_mutex_unlock(queue->one_big_mutex);
    }

    return rv;
}
예제 #8
0
/**
 * etch_apr_queue_unsafe_interrupt_all()
 * added by Cisco to opeate when lock already held since queue lock is not nestable.
 */
apr_status_t etch_apr_queue_unsafe_interrupt_all(etch_apr_queue_t *queue)
{
    Q_DBG("intr all", queue);    
 
    apr_thread_cond_broadcast(queue->not_empty);
    apr_thread_cond_broadcast(queue->not_full);

    return APR_SUCCESS;
}
예제 #9
0
apr_status_t etch_apr_queue_interrupt_all(etch_apr_queue_t *queue)
{
    apr_status_t rv;
    Q_DBG("intr all", queue); 
   
    if (APR_SUCCESS == (rv = apr_thread_mutex_lock(queue->one_big_mutex)))
    { 
        apr_thread_cond_broadcast(queue->not_empty);
        apr_thread_cond_broadcast(queue->not_full);

        apr_thread_mutex_unlock(queue->one_big_mutex);
    }

    return rv;
}
예제 #10
0
APU_DECLARE(apr_status_t) apr_queue_interrupt_all(apr_queue_t *queue)
{
    apr_status_t rv;
    Q_DBG("intr all", queue);    
    if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) {
        return rv;
    }
    apr_thread_cond_broadcast(queue->not_empty);
    apr_thread_cond_broadcast(queue->not_full);

    if ((rv = apr_thread_mutex_unlock(queue->one_big_mutex)) != APR_SUCCESS) {
        return rv;
    }

    return APR_SUCCESS;
}
예제 #11
0
/**
 * Retrieves the next item from the queue. If there are no
 * items available, it will block until one becomes available.
 * Once retrieved, the item is placed into the address specified by
 * 'data'.
 * @param timeout added by Cisco. now uses apr_thread_cond_timewait(). 
 * interval of time to wait. zero means forever, -1 means no wait, 
 * -2 means don't wait and ignore queue closed indicator,
 * otherwise timeout is blocking time in microseconds.
 * @return APR_SUCCESS, APR_EAGAIN, APR_EOF, APR_EINTR, APR_TIMEUP, 
 * or some APR error
 */
apr_status_t etch_apr_queue_pop(etch_apr_queue_t *queue, 
                                apr_interval_time_t timeout, 
                                void **data)
{
    apr_status_t rv;

    if (queue->terminated)  /* Cisco back door to clear closed queue */
    {   if (timeout != ETCHQUEUE_CLEARING_CLOSED_QUEUE)  
            return APR_EOF; /* no more elements ever again */
    }

    if (APR_SUCCESS == (rv = apr_thread_mutex_lock(queue->one_big_mutex)))
    {
        do 
        {   /* Keep waiting until we wake up and find that the queue is not empty. */
            if (etch_apr_queue_empty(queue)) 
            {
                if (-1 == timeout) 
                {   rv = APR_EAGAIN; /* asked to not wait */
                    break;
                }

                if (!queue->terminated) 
                {
                    queue->empty_waiters++;

                    if (0 == timeout)
                        rv = apr_thread_cond_wait(queue->not_empty, queue->one_big_mutex);
                    else 
                        rv = apr_thread_cond_timedwait(queue->not_empty, queue->one_big_mutex, timeout);

                    queue->empty_waiters--;

                    if (rv != APR_SUCCESS) /* rv will be APR_TIMEUP if timed out */ 
                        break;
                }

                /* If we wake up and it's still empty, then we were interrupted */
                if (etch_apr_queue_empty(queue)) 
                {
                    Q_DBG("queue empty (intr)", queue);
                    rv = queue->terminated? APR_EOF: APR_EINTR;
                    break;
                }
            } 

            *data = queue->data[queue->out];
            queue->nelts--;

            queue->out = (queue->out + 1) % queue->bounds;

            if (queue->full_waiters) 
            {
                Q_DBG("signal !full", queue);
                rv = apr_thread_cond_signal(queue->not_full);
            }

        } while(0);

        apr_thread_mutex_unlock(queue->one_big_mutex);
    }  

    return rv;
}