/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
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; }
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; }
/** * 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; }