Ejemplo n.º 1
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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
apr_status_t h2_beam_send(h2_bucket_beam *beam, 
                          apr_bucket_brigade *red_brigade, 
                          apr_read_type_e block)
{
    apr_bucket *bred;
    apr_status_t status = APR_SUCCESS;
    h2_beam_lock bl;

    /* Called from the red thread to add buckets to the beam */
    if (enter_yellow(beam, &bl) == APR_SUCCESS) {
        r_purge_reds(beam);
        
        if (beam->aborted) {
            status = APR_ECONNABORTED;
        }
        else if (red_brigade) {
            int force_report = !APR_BRIGADE_EMPTY(red_brigade); 
            while (!APR_BRIGADE_EMPTY(red_brigade)
                   && status == APR_SUCCESS) {
                bred = APR_BRIGADE_FIRST(red_brigade);
                status = append_bucket(beam, bred, block, beam->red_pool, &bl);
            }
            report_production(beam, force_report);
            if (beam->m_cond) {
                apr_thread_cond_broadcast(beam->m_cond);
            }
        }
        report_consumption(beam, 0);
        leave_yellow(beam, &bl);
    }
    return status;
}
Ejemplo n.º 4
0
apr_status_t h2_beam_shutdown(h2_bucket_beam *beam, apr_read_type_e block)
{
    apr_status_t status;
    h2_beam_lock bl;
    
    if ((status = enter_yellow(beam, &bl)) == APR_SUCCESS) {
        r_purge_reds(beam);
        h2_blist_cleanup(&beam->red);
        beam_close(beam);
        report_consumption(beam, 0);
        
        while (status == APR_SUCCESS 
               && (!H2_BPROXY_LIST_EMPTY(&beam->proxies)
                   || (beam->green && !APR_BRIGADE_EMPTY(beam->green)))) {
            if (block == APR_NONBLOCK_READ || !bl.mutex) {
                status = APR_EAGAIN;
                break;
            }
            if (beam->m_cond) {
                apr_thread_cond_broadcast(beam->m_cond);
            }
            status = wait_cond(beam, bl.mutex);
        }
        leave_yellow(beam, &bl);
    }
    return status;
}
Ejemplo n.º 5
0
void single_gop_mark_completed(op_generic_t *gop, op_status_t status)
{
    op_common_t *base = &(gop->base);
    int mode;

    log_printf(15, "gop_mark_completed: START gid=%d status=%d\n", gop_id(gop), status.op_status);

    lock_gop(gop);
    log_printf(15, "gop_mark_completed: after lock gid=%d\n", gop_id(gop));

    //** Store the status
    base->status = status;

    //** and trigger any callbacks

    log_printf(15, "gop_mark_completed: before cb gid=%d op_status=%d\n", gop_id(gop), base->status.op_status);

    callback_execute(base->cb, base->status.op_status);

    log_printf(15, "gop_mark_completed: after cb gid=%d op_success=%d\n", gop_id(gop), base->status.op_status);

    base->state = 1;

    //** Lastly trigger the signal. for anybody listening
    apr_thread_cond_broadcast(gop->base.ctl->cond);

    log_printf(15, "gop_mark_completed: after brodcast gid=%d\n", gop_id(gop));

    mode = gop_get_auto_destroy(gop);  //** Get the auto destroy status w/in the lock

    unlock_gop(gop);

    //** Check if we do an auto cleanop
    if (mode == 1) gop_free(gop, OP_DESTROY);
}
Ejemplo n.º 6
0
static void pong(toolbox_t *box)
{
    apr_status_t rv;
    abts_case *tc = box->tc;

    rv = apr_thread_mutex_lock(box->mutex);
    ABTS_SUCCESS(rv);

    if (state == TOSS)
        state = PONG;

    do {
        rv = apr_thread_cond_signal(box->cond);
        ABTS_SUCCESS(rv);

        state = PING;

        rv = apr_thread_cond_wait(box->cond, box->mutex);
        ABTS_SUCCESS(rv);

        ABTS_TRUE(tc, state == PONG || state == OVER);
    } while (state != OVER);

    rv = apr_thread_mutex_unlock(box->mutex);
    ABTS_SUCCESS(rv);

    rv = apr_thread_cond_broadcast(box->cond);
    ABTS_SUCCESS(rv);
}
Ejemplo n.º 7
0
static apr_size_t trim_idle_threads(apr_thread_pool_t *me, apr_size_t cnt)
{
    apr_size_t n_dbg;
    struct apr_thread_list_elt *elt, *head, *tail;
    apr_status_t rv;

    elt = trim_threads(me, &cnt, 1);

    apr_thread_mutex_lock(me->lock);
    apr_thread_cond_broadcast(me->cond);
    apr_thread_mutex_unlock(me->lock);

    n_dbg = 0;
    if (NULL != (head = elt)) {
        while (elt) {
            tail = elt;
            apr_thread_join(&rv, elt->thd);
            elt = APR_RING_NEXT(elt, link);
            ++n_dbg;
        }
        apr_thread_mutex_lock(me->lock);
        APR_RING_SPLICE_TAIL(me->recycled_thds, head, tail,
                             apr_thread_list_elt, link);
        apr_thread_mutex_unlock(me->lock);
    }
    assert(cnt == n_dbg);

    return cnt;
}
Ejemplo n.º 8
0
static void broadcast_threads(abts_case *tc, void *data)
{
    toolbox_t box;
    unsigned int i;
    apr_status_t rv;
    apr_uint32_t count = 0;
    apr_thread_cond_t *cond = NULL;
    apr_thread_mutex_t *mutex = NULL;
    apr_thread_t *thread[NTHREADS];

    rv = apr_thread_cond_create(&cond, p);
    ABTS_SUCCESS(rv);
    ABTS_PTR_NOTNULL(tc, cond);

    rv = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, p);
    ABTS_SUCCESS(rv);
    ABTS_PTR_NOTNULL(tc, mutex);

    rv = apr_thread_mutex_lock(mutex);
    ABTS_SUCCESS(rv);

    box.tc = tc;
    box.data = &count;
    box.mutex = mutex;
    box.cond = cond;
    box.func = lock_and_wait;

    for (i = 0; i < NTHREADS; i++) {
        rv = apr_thread_create(&thread[i], NULL, thread_routine, &box, p);
        ABTS_SUCCESS(rv);
    }

    do {
        rv = apr_thread_mutex_unlock(mutex);
        ABTS_SUCCESS(rv);
        apr_sleep(100000);
        rv = apr_thread_mutex_lock(mutex);
        ABTS_SUCCESS(rv);
    } while (apr_atomic_read32(&count) != NTHREADS);

    rv = apr_thread_cond_broadcast(cond);
    ABTS_SUCCESS(rv);

    rv = apr_thread_mutex_unlock(mutex);
    ABTS_SUCCESS(rv);

    for (i = 0; i < NTHREADS; i++) {
        apr_status_t retval;
        rv = apr_thread_join(&retval, thread[i]);
        ABTS_SUCCESS(rv);
    }

    ABTS_INT_EQUAL(tc, 0, count);

    rv = apr_thread_cond_destroy(cond);
    ABTS_SUCCESS(rv);

    rv = apr_thread_mutex_destroy(mutex);
    ABTS_SUCCESS(rv);
}
Ejemplo n.º 9
0
void rs_simple_destroy(resource_service_fn_t *rs)
{
    rs_simple_priv_t *rss = (rs_simple_priv_t *)rs->priv;
    apr_status_t value;

    log_printf(15, "rs_simple_destroy: sl=%p\n", rss->rid_table);
    tbx_log_flush();

    //** Notify the depot check thread
    apr_thread_mutex_lock(rss->lock);
    rss->shutdown = 1;
    apr_thread_cond_broadcast(rss->cond);
    apr_thread_mutex_unlock(rss->lock);

    //** Wait for it to shutdown
    apr_thread_join(&value, rss->check_thread);

    //** Now we can free up all the space
    apr_thread_mutex_destroy(rss->lock);
    apr_thread_cond_destroy(rss->cond);
    apr_pool_destroy(rss->mpool);  //** This also frees the hash tables

    if (rss->rid_table != NULL) tbx_list_destroy(rss->rid_table);

    free(rss->random_array);
    free(rss->fname);
    free(rss);
    free(rs);
}
Ejemplo n.º 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;
}
static int
on_topic_add_discard(SESSION_T *session, void *context)
{
        apr_thread_mutex_lock(mutex);
        apr_thread_cond_broadcast(cond);
        apr_thread_mutex_unlock(mutex);
        return HANDLER_SUCCESS;
}
Ejemplo n.º 12
0
op_status_t mqs_response_client_more(void *task_arg, int tid)
{
    mq_task_t *task = (mq_task_t *)task_arg;
    mq_stream_t *mqs = (mq_stream_t *)task->arg;
    op_status_t status = op_success_status;

    log_printf(5, "START msid=%d\n", mqs->msid);

    //** Parse the response
    mq_remove_header(task->response, 1);

    //** Wait for a notification that the data can be processed
    apr_thread_mutex_lock(mqs->lock);
    log_printf(5, "INIT STATUS msid=%d waiting=%d processed=%d\n", mqs->msid, mqs->waiting, mqs->processed);
    mqs->transfer_packets++;
    mqs->waiting = 0;
    apr_thread_cond_broadcast(mqs->cond);

    //** Now wait until the application is ready
    while (mqs->waiting == 0) {
        apr_thread_cond_wait(mqs->cond, mqs->lock);
    }

    //** Can accept the data
    mq_get_frame(mq_msg_first(task->response), (void **)&(mqs->data), &(mqs->len));
    pack_read_new_data(mqs->pack, &(mqs->data[MQS_HEADER]), mqs->len-MQS_HEADER);

    //** Notify the consumer it's available
    mqs->waiting = -2;
    apr_thread_cond_broadcast(mqs->cond);

    //** Wait until it's consumed
    while (mqs->processed == 0) {
        apr_thread_cond_wait(mqs->cond, mqs->lock);
    }

    mqs->data = NULL;    //** Nullify the data so it's not accidentally accessed
    mqs->processed = 0;  //** and reset the processed flag back to 0

    apr_thread_mutex_unlock(mqs->lock);

    log_printf(5, "END msid=%d status=%d %d\n", mqs->msid, status.op_status, status.error_code);

    return(status);
}
Ejemplo n.º 13
0
static int
on_topic_removed(SESSION_T *session, const SVC_REMOVE_TOPICS_RESPONSE_T *response, void *context)
{
        puts("on_topic_removed");
        apr_thread_mutex_lock(mutex);
        apr_thread_cond_broadcast(cond);
        apr_thread_mutex_unlock(mutex);
        return HANDLER_SUCCESS;
}
static int
on_topic_add_failed(SESSION_T *session, const SVC_ADD_TOPIC_RESPONSE_T *response, void *context)
{
        printf("Failed to add topic (%d)\n", response->response_code);
        apr_thread_mutex_lock(mutex);
        apr_thread_cond_broadcast(cond);
        apr_thread_mutex_unlock(mutex);
        return HANDLER_SUCCESS;
}
Ejemplo n.º 15
0
apr_status_t ap_queue_interrupt_all(fd_queue_t *queue)
{
    apr_status_t rv;

    if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) {
        return rv;
    }
    apr_thread_cond_broadcast(queue->not_empty);
    return apr_thread_mutex_unlock(queue->one_big_mutex);
}
Ejemplo n.º 16
0
static apr_status_t beam_close(h2_bucket_beam *beam)
{
    if (!beam->closed) {
        beam->closed = 1;
        if (beam->m_cond) {
            apr_thread_cond_broadcast(beam->m_cond);
        }
    }
    return APR_SUCCESS;
}
Ejemplo n.º 17
0
apr_status_t ap_queue_info_term(fd_queue_info_t *queue_info)
{
    apr_status_t rv;
    rv = apr_thread_mutex_lock(queue_info->idlers_mutex);
    if (rv != APR_SUCCESS) {
        return rv;
    }
    queue_info->terminated = 1;
    apr_thread_cond_broadcast(queue_info->wait_for_idler);
    return apr_thread_mutex_unlock(queue_info->idlers_mutex);
}
static int
on_update_source_deregistered(SESSION_T *session,
                              const CONVERSATION_ID_T *updater_id,
                              void *context)
{
        char *id_str = conversation_id_to_string(*updater_id);
        printf("Deregistered update source \"%s\"\n", id_str);
        free(id_str);
        apr_thread_mutex_lock(mutex);
        apr_thread_cond_broadcast(cond);
        apr_thread_mutex_unlock(mutex);
        return HANDLER_SUCCESS;}
Ejemplo n.º 19
0
/**
 * Callback invoked when/if a message is sent on the topic that the
 * client is writing to.
 */
static int
on_send(SESSION_T *session, void *context)
{
        printf("on_send() successful. Context=\"%s\".\n", (char *)context);

        // Allow main thread to continue.
        apr_thread_mutex_lock(mutex);
        apr_thread_cond_broadcast(cond);
        apr_thread_mutex_unlock(mutex);

        return HANDLER_SUCCESS;
}
Ejemplo n.º 20
0
void gop_finished_submission(op_generic_t *g)
{
    lock_gop(g);
    if (gop_get_type(g) == Q_TYPE_QUE) {
        g->q->finished_submission = 1;

        //** If nothing left to do trigger the condition in case anyone's waiting
        if (g->q->nleft == 0) {
            apr_thread_cond_broadcast(g->base.ctl->cond);
        }
    }
    unlock_gop(g);
}
/*
 * Handlers for registration of update source feature
 */
static int
on_update_source_init(SESSION_T *session,
                      const CONVERSATION_ID_T *updater_id,
                      const SVC_UPDATE_REGISTRATION_RESPONSE_T *response,
                      void *context)
{
        char *id_str = conversation_id_to_string(*updater_id);
        printf("Topic source \"%s\" in init state\n", id_str);
        free(id_str);
        apr_thread_mutex_lock(mutex);
        apr_thread_cond_broadcast(cond);
        apr_thread_mutex_unlock(mutex);
        return HANDLER_SUCCESS;
}
Ejemplo n.º 22
0
void h2_beam_abort(h2_bucket_beam *beam)
{
    h2_beam_lock bl;
    
    if (enter_yellow(beam, &bl) == APR_SUCCESS) {
        r_purge_reds(beam);
        h2_blist_cleanup(&beam->red);
        beam->aborted = 1;
        report_consumption(beam, 0);
        if (beam->m_cond) {
            apr_thread_cond_broadcast(beam->m_cond);
        }
        leave_yellow(beam, &bl);
    }
}
Ejemplo n.º 23
0
static void lost_signal(abts_case *tc, void *data)
{
    apr_status_t rv;
    apr_thread_cond_t *cond = NULL;
    apr_thread_mutex_t *mutex = NULL;

    rv = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, p);
    ABTS_SUCCESS(rv);
    ABTS_PTR_NOTNULL(tc, mutex);

    rv = apr_thread_cond_create(&cond, p);
    ABTS_SUCCESS(rv);
    ABTS_PTR_NOTNULL(tc, cond);

    rv = apr_thread_cond_signal(cond);
    ABTS_SUCCESS(rv);

    rv = apr_thread_mutex_lock(mutex);
    ABTS_SUCCESS(rv);

    rv = apr_thread_cond_timedwait(cond, mutex, 10000);
    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));

    rv = apr_thread_mutex_unlock(mutex);
    ABTS_SUCCESS(rv);

    rv = apr_thread_cond_broadcast(cond);
    ABTS_SUCCESS(rv);

    rv = apr_thread_mutex_lock(mutex);
    ABTS_SUCCESS(rv);

    rv = apr_thread_cond_timedwait(cond, mutex, 10000);
    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));

    rv = apr_thread_mutex_unlock(mutex);
    ABTS_SUCCESS(rv);

    rv = apr_thread_cond_destroy(cond);
    ABTS_SUCCESS(rv);

    rv = apr_thread_mutex_destroy(mutex);
    ABTS_SUCCESS(rv);
}
Ejemplo n.º 24
0
void gop_dummy_destroy()
{
    apr_status_t tstat;

//** Signal a shutdown
    apr_thread_mutex_lock(gd_lock);
    gd_shutdown = 1;
    apr_thread_cond_broadcast(gd_cond);
    apr_thread_mutex_unlock(gd_lock);

//** Wait for the thread to complete
    apr_thread_join(&tstat, gd_thread);

    //** Clean up;
    free_stack(gd_stack, 0);
    apr_thread_mutex_destroy(gd_lock);
    apr_thread_cond_destroy(gd_cond);
    apr_pool_destroy(gd_pool);
}
Ejemplo n.º 25
0
void rss_mapping_notify(resource_service_fn_t *rs, int new_version, int status_change)
{
    rs_simple_priv_t *rss = (rs_simple_priv_t *)rs->priv;
    apr_hash_index_t *hi;
    rs_mapping_notify_t *rsn;
    apr_ssize_t klen;
    void *rid;

    if (status_change > 0) status_change = tbx_random_get_int64(0, 100000);

    apr_thread_mutex_lock(rss->update_lock);
    for (hi = apr_hash_first(NULL, rss->mapping_updates); hi != NULL; hi = apr_hash_next(hi)) {
        apr_hash_this(hi, (const void **)&rid, &klen, (void **)&rsn);
        apr_thread_mutex_lock(rsn->lock);
        rsn->map_version = new_version;
        if (status_change > 0) rsn->status_version = status_change;
        apr_thread_cond_broadcast(rsn->cond);
        apr_thread_mutex_unlock(rsn->lock);
    }
    apr_thread_mutex_unlock(rss->update_lock);
}
Ejemplo n.º 26
0
void LLConditionVariableImpl::notify_all()
{
	APRExceptionThrower(apr_thread_cond_broadcast(mConditionVariableImpl));
}
Ejemplo n.º 27
0
static void pipe_producer_consumer(abts_case *tc, void *data)
{
    apr_status_t rv;
    toolbox_t boxcons, boxprod;
    apr_thread_t *thread[NTHREADS];
    apr_thread_cond_t *cond = NULL;
    apr_thread_mutex_t *mutex = NULL;
    apr_file_t *in = NULL, *out = NULL;
    apr_uint32_t i, ncons = (apr_uint32_t)(NTHREADS * 0.70);

    rv = apr_file_pipe_create(&in, &out, p);
    ABTS_SUCCESS(rv);

    rv = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, p);
    ABTS_SUCCESS(rv);
    ABTS_PTR_NOTNULL(tc, mutex);

    rv = apr_thread_cond_create(&cond, p);
    ABTS_SUCCESS(rv);
    ABTS_PTR_NOTNULL(tc, cond);

    boxcons.tc = tc;
    boxcons.data = in;
    boxcons.mutex = mutex;
    boxcons.cond = cond;
    boxcons.func = pipe_consumer;

    for (i = 0; i < ncons; i++) {
        rv = apr_thread_create(&thread[i], NULL, thread_routine, &boxcons, p);
        ABTS_SUCCESS(rv);
    }

    boxprod.tc = tc;
    boxprod.data = out;
    boxprod.mutex = mutex;
    boxprod.cond = cond;
    boxprod.func = pipe_producer;

    for (; i < NTHREADS; i++) {
        rv = apr_thread_create(&thread[i], NULL, thread_routine, &boxprod, p);
        ABTS_SUCCESS(rv);
    }

    for (i = ncons; i < NTHREADS; i++) {
        apr_status_t retval;
        rv = apr_thread_join(&retval, thread[i]);
        ABTS_SUCCESS(rv);
    }

    rv = apr_thread_mutex_lock(mutex);
    ABTS_SUCCESS(rv);

    exiting = 1;

    rv = apr_thread_cond_broadcast(cond);
    ABTS_SUCCESS(rv);

    rv = apr_thread_mutex_unlock(mutex);
    ABTS_SUCCESS(rv);

    for (i = 0; i < ncons; i++) {
        apr_status_t retval;
        rv = apr_thread_join(&retval, thread[i]);
        ABTS_SUCCESS(rv);
    }

    rv = apr_thread_cond_destroy(cond);
    ABTS_SUCCESS(rv);

    rv = apr_thread_mutex_destroy(mutex);
    ABTS_SUCCESS(rv);

    rv = apr_file_close(in);
    ABTS_SUCCESS(rv);

    rv = apr_file_close(out);
    ABTS_SUCCESS(rv);
}
Ejemplo n.º 28
0
void LLCondition::broadcast()
{
	apr_thread_cond_broadcast(mAPRCondp);
}
Ejemplo n.º 29
0
SWITCH_DECLARE(switch_status_t) switch_thread_cond_broadcast(switch_thread_cond_t *cond)
{
	return apr_thread_cond_broadcast(cond);
}
Ejemplo n.º 30
0
int mq_stream_read_wait(mq_stream_t *mqs)
{
    int err = 0;
    apr_interval_time_t dt;
    op_status_t status;

    //** If 1st time make all the variables
    if (mqs->mpool == NULL) {
        apr_pool_create(&mqs->mpool, NULL);
        apr_thread_mutex_create(&(mqs->lock), APR_THREAD_MUTEX_DEFAULT, mqs->mpool);
        apr_thread_cond_create(&(mqs->cond), mqs->mpool);
    }

    dt = apr_time_from_sec(1);


    //** Flag the just processed gop to clean up
    apr_thread_mutex_lock(mqs->lock);
    log_printf(5, "START msid=%d waiting=%d processed=%d gop_processed=%p\n", mqs->msid, mqs->waiting, mqs->processed, mqs->gop_processed);
    if (mqs->gop_processed != NULL) mqs->processed = 1;
    apr_thread_cond_broadcast(mqs->cond);

    if (mqs->data) {
        if (mqs->data[MQS_STATE_INDEX] != MQS_MORE) err = 1;
    }
    apr_thread_mutex_unlock(mqs->lock);

    if (mqs->gop_processed != NULL) {
        gop_waitany(mqs->gop_processed);
        gop_free(mqs->gop_processed, OP_DESTROY);
        mqs->gop_processed = NULL;
    }

    if (err != 0) {
        log_printf(2, "ERROR no more data available!\n");
        return(-1);
    }

    //** Now handle the waiting gop
    apr_thread_mutex_lock(mqs->lock);
    log_printf(5, "before loop msid=%d waiting=%d processed=%d\n", mqs->msid, mqs->waiting, mqs->processed);

    while (mqs->waiting == 1) {
        log_printf(5, "LOOP msid=%d waiting=%d processed=%d\n", mqs->msid, mqs->waiting, mqs->processed);
        if (gop_will_block(mqs->gop_waiting) == 0)  { //** Oops!  failed request
            status = gop_get_status(mqs->gop_waiting);
            log_printf(2, "msid=%d gid=%d status=%d\n", mqs->msid, gop_id(mqs->gop_waiting), status.op_status);
            if (status.op_status != OP_STATE_SUCCESS) {
                mqs->waiting = -3;
                err = 1;
            } else {
                apr_thread_cond_timedwait(mqs->cond, mqs->lock, dt);
            }
        } else {
            apr_thread_cond_timedwait(mqs->cond, mqs->lock, dt);
        }
    }

    if (mqs->waiting == 0) {  //** Flag the receiver to accept the data
        mqs->waiting = -1;
        apr_thread_cond_broadcast(mqs->cond);  //** Let the receiver know we're ready to accept the data

        //** Wait for the data to be accepted
        while (mqs->waiting != -2) {
            apr_thread_cond_wait(mqs->cond, mqs->lock);
        }
    } else if (mqs->waiting == -3) { //**error occured
        err = 1;
    }
    apr_thread_mutex_unlock(mqs->lock);

    //** Flip states
    mqs->gop_processed = mqs->gop_waiting;
    mqs->gop_waiting = NULL;

    //** This shouldn't get triggered but just in case lets throw an error.
    if ((mqs->gop_processed == NULL) && (mqs->data != NULL)) {
        if ((mqs->data[MQS_STATE_INDEX] == MQS_MORE) && (mqs->want_more == MQS_MORE)) {
            err = 3;
            log_printf(0, "ERROR: MQS gop processed=waiting=NULL  want_more set!!!!!! err=%d\n", err);
            fprintf(stderr, "ERROR: MQS gop processed=waiting=NULL want_more set!!!!!! err=%d\n", err);
        }
    }

    //** Check if we need to fire off the next request
    if (mqs->data != NULL) {
        if ((mqs->data[MQS_STATE_INDEX] == MQS_MORE) && (mqs->want_more == MQS_MORE)) {
            mq_stream_read_request(mqs);
        }
    }

    log_printf(5, "err=%d\n", err);
    return(err);
}