示例#1
0
op_generic_t *gop_timed_waitany(op_generic_t *g, int dt)
{
    op_generic_t *gop = NULL;
    apr_interval_time_t adt = apr_time_from_sec(dt);
    int loop;

    lock_gop(g);
    _gop_start_execution(g);  //** Make sure things have been submitted

    loop = 0;
    if (gop_get_type(g) == Q_TYPE_QUE) {
        while (((gop = (op_generic_t *)pop(g->q->finished)) == NULL) && (g->q->nleft > 0) && (loop == 0)) {
            apr_thread_cond_timedwait(g->base.ctl->cond, g->base.ctl->lock, adt); //** Sleep until something completes
            loop++;
        }
    } else {
        while ((g->base.state == 0) && (loop == 0)) {
            apr_thread_cond_timedwait(g->base.ctl->cond, g->base.ctl->lock, adt); //** Sleep until something completes
            loop++;
        }

        if (g->base.state != 0) gop = g;
    }
    unlock_gop(g);

    return(gop);
}
示例#2
0
int gop_timed_waitall(op_generic_t *g, int dt)
{
    int status;
    int loop;
    apr_interval_time_t adt = apr_time_from_sec(dt);

    lock_gop(g);
    _gop_start_execution(g);  //** Make sure things have been submitted

    loop = 0;
    if (gop_get_type(g) == Q_TYPE_QUE) {
        while ((g->q->nleft > 0) && (loop == 0)) {
            apr_thread_cond_timedwait(g->base.ctl->cond, g->base.ctl->lock, adt); //** Sleep until something completes
            loop++;
        }

        status = (g->q->nleft > 0) ? OP_STATE_RETRY : _gop_completed_successfully(g);
    } else {
        while ((g->base.state == 0) && (loop == 0)) {
            apr_thread_cond_timedwait(g->base.ctl->cond, g->base.ctl->lock, adt); //** Sleep until something completes
            loop++;
        }

        status = (g->base.state == 0) ? OP_STATE_RETRY : _gop_completed_successfully(g);
    }

    unlock_gop(g);

    return(status);
}
示例#3
0
apr_status_t h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait)
{
    apr_status_t status;
    workers_unregister(m);

    status = apr_thread_mutex_lock(m->lock);
    if (APR_SUCCESS == status) {
        int attempts = 0;
        
        release(m);
        while (apr_atomic_read32(&m->refs) > 0) {
            m->join_wait = wait;
            ap_log_cerror(APLOG_MARK, (attempts? APLOG_INFO : APLOG_DEBUG), 
                          0, m->c,
                          "h2_mplx(%ld): release_join, refs=%d, waiting...", 
                          m->id, m->refs);
            apr_thread_cond_timedwait(wait, m->lock, apr_time_from_sec(10));
            if (++attempts >= 6) {
                ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c,
                              APLOGNO(02952) 
                              "h2_mplx(%ld): join attempts exhausted, refs=%d", 
                              m->id, m->refs);
                break;
            }
        }
        if (m->join_wait) {
            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, m->c,
                          "h2_mplx(%ld): release_join -> destroy", m->id);
        }
        m->join_wait = NULL;
        apr_thread_mutex_unlock(m->lock);
        h2_mplx_destroy(m);
    }
    return status;
}
示例#4
0
文件: h2_mplx.c 项目: Sp1l/mod_h2
apr_status_t h2_mplx_out_trywait(h2_mplx *m, apr_interval_time_t timeout,
                                 apr_thread_cond_t *iowait)
{
    apr_status_t status;
    int acquired;
    
    AP_DEBUG_ASSERT(m);
    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
        if (m->aborted) {
            status = APR_ECONNABORTED;
        }
        else {
            m->added_output = iowait;
            status = apr_thread_cond_timedwait(m->added_output, m->lock, timeout);
            if (APLOGctrace2(m->c)) {
                ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
                              "h2_mplx(%ld): trywait on data for %f ms)",
                              m->id, timeout/1000.0);
            }
            m->added_output = NULL;
        }
        leave_mutex(m, acquired);
    }
    return status;
}
示例#5
0
ASR_CLIENT_DECLARE(const char*) asr_session_wait_for_termination(
									asr_session_t *asr_session)
{
	const mrcp_app_message_t *app_message = NULL;
	mrcp_message_t *mrcp_message = NULL;

	/* Wait for events either START-OF-INPUT or RECOGNITION-COMPLETE */
	do {
		apr_thread_mutex_lock(asr_session->mutex);
		app_message = NULL;
		if(apr_thread_cond_timedwait(asr_session->wait_object,asr_session->mutex, 60 * 1000000) != APR_SUCCESS) {
			apr_thread_mutex_unlock(asr_session->mutex);
			return NULL;
		}
		app_message = asr_session->app_message;
		asr_session->app_message = NULL;
		apr_thread_mutex_unlock(asr_session->mutex);

		mrcp_message = mrcp_event_get(app_message);
		if(mrcp_message && mrcp_message->start_line.method_id == RECOGNIZER_RECOGNITION_COMPLETE) {
			asr_session->recog_complete = mrcp_message;
		}
	}
	while(!asr_session->recog_complete);

	/* Get results */
	return nlsml_input_get(asr_session->recog_complete);
}
示例#6
0
static void dynamic_binding(abts_case *tc, void *data)
{
    unsigned int i;
    apr_status_t rv;
    toolbox_t box[NTHREADS];
    apr_thread_t *thread[NTHREADS];
    apr_thread_mutex_t *mutex[NTHREADS];
    apr_thread_cond_t *cond = NULL;

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

    for (i = 0; i < NTHREADS; i++) {
        rv = apr_thread_mutex_create(&mutex[i], APR_THREAD_MUTEX_DEFAULT, p);
        ABTS_SUCCESS(rv);

        rv = apr_thread_mutex_lock(mutex[i]);
        ABTS_SUCCESS(rv);

        box[i].tc = tc;
        box[i].cond = cond;
        box[i].mutex = mutex[i];
        box[i].func = lock_and_signal;

        rv = apr_thread_create(&thread[i], NULL, thread_routine, &box[i], p);
        ABTS_SUCCESS(rv);
    }

    /*
     * The dynamic binding should be preserved because we use only one waiter
     */

    for (i = 0; i < NTHREADS; i++) {
        rv = apr_thread_cond_wait(cond, mutex[i]);
        ABTS_SUCCESS(rv);
    }

    for (i = 0; i < NTHREADS; i++) {
        rv = apr_thread_cond_timedwait(cond, mutex[i], 10000);
        ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));

        rv = apr_thread_mutex_unlock(mutex[i]);
        ABTS_SUCCESS(rv);
    }

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

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

    for (i = 0; i < NTHREADS; i++) {
        rv = apr_thread_mutex_destroy(mutex[i]);
        ABTS_SUCCESS(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.
 * @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;
}
示例#8
0
static apr_status_t wait_cond(h2_bucket_beam *beam, apr_thread_mutex_t *lock)
{
    if (beam->timeout > 0) {
        return apr_thread_cond_timedwait(beam->m_cond, lock, beam->timeout);
    }
    else {
        return apr_thread_cond_wait(beam->m_cond, lock);
    }
}
示例#9
0
void hportal_wait(host_portal_t *hp, int dt)
{
    apr_time_t t;

    if (dt < 0) return;   //** If negative time has run out so return

    tbx_ns_timeout_set(&t, dt, 0);
    apr_thread_cond_timedwait(hp->cond, hp->lock, t);
}
示例#10
0
/* Stop SPEAK/RECOGNIZE request on speech channel. */
int speech_channel_stop(speech_channel_t *schannel)
{
	int status = 0;

	if (schannel == NULL)
		return -1;

	if (schannel->mutex != NULL)
		apr_thread_mutex_lock(schannel->mutex);

	if (schannel->state == SPEECH_CHANNEL_PROCESSING) {
		mrcp_method_id method;
		mrcp_message_t *mrcp_message;

		if (schannel->type == SPEECH_CHANNEL_SYNTHESIZER)
			method = SYNTHESIZER_STOP;
		else
			method = RECOGNIZER_STOP;

		ast_log(LOG_DEBUG, "(%s) Stopping %s\n", schannel->name, speech_channel_type_to_string(schannel->type));

		/* Send STOP to MRCP server. */
		mrcp_message = mrcp_application_message_create(schannel->unimrcp_session, schannel->unimrcp_channel, method);

		if (mrcp_message == NULL) {
			ast_log(LOG_ERROR, "(%s) Failed to create STOP message\n", schannel->name);
			status = -1;
		} else {
			if (!mrcp_application_message_send(schannel->unimrcp_session, schannel->unimrcp_channel, mrcp_message))
				ast_log(LOG_WARNING, "(%s) Failed to send STOP message\n", schannel->name);
			else if (schannel->cond != NULL) {
				while (schannel->state == SPEECH_CHANNEL_PROCESSING) {
					if (apr_thread_cond_timedwait(schannel->cond, schannel->mutex, SPEECH_CHANNEL_TIMEOUT_USEC) == APR_TIMEUP) {
						break;
					}
				}
			}

			if (schannel->state == SPEECH_CHANNEL_PROCESSING) {
				ast_log(LOG_ERROR, "(%s) Timed out waiting for session to close.  Continuing\n", schannel->name);
				schannel->state = SPEECH_CHANNEL_ERROR;
				status = -1;
			} else if (schannel->state == SPEECH_CHANNEL_ERROR) {
				ast_log(LOG_ERROR, "(%s) Channel error\n", schannel->name);
				schannel->state = SPEECH_CHANNEL_ERROR;
				status = -1;
			} else {
				ast_log(LOG_DEBUG, "(%s) %s stopped\n", schannel->name, speech_channel_type_to_string(schannel->type));
			}
		}
	}

	if (schannel->mutex != NULL)
		apr_thread_mutex_unlock(schannel->mutex);

	return status;
}
示例#11
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);
}
示例#12
0
文件: switch_apr.c 项目: gujun/sscore
SWITCH_DECLARE(switch_status_t) switch_thread_cond_timedwait(switch_thread_cond_t *cond, switch_mutex_t *mutex, switch_interval_time_t timeout)
{
	apr_status_t st = apr_thread_cond_timedwait(cond, mutex, timeout);

	if (st == APR_TIMEUP) {
		st = SWITCH_STATUS_TIMEOUT;
	}

	return st;
}
示例#13
0
APU_DECLARE(apr_status_t) apr_reslist_acquire(apr_reslist_t *reslist,
                                              void **resource)
{
    apr_status_t rv;
    apr_res_t *res;

    apr_thread_mutex_lock(reslist->listlock);
    /* If there are idle resources on the available list, use
     * them right away. */
    if (reslist->nidle > 0) {
        /* Pop off the first resource */
        res = pop_resource(reslist);
        *resource = res->opaque;
        free_container(reslist, res);
        apr_thread_mutex_unlock(reslist->listlock);
        return APR_SUCCESS;
    }
    /* If we've hit our max, block until we're allowed to create
     * a new one, or something becomes free. */
    else while (reslist->ntotal >= reslist->hmax
                && reslist->nidle <= 0) {
        if (reslist->timeout) {
            if ((rv = apr_thread_cond_timedwait(reslist->avail, 
                reslist->listlock, reslist->timeout)) != APR_SUCCESS) {
                apr_thread_mutex_unlock(reslist->listlock);
                return rv;
            }
        }
        else
            apr_thread_cond_wait(reslist->avail, reslist->listlock);
    }
    /* If we popped out of the loop, first try to see if there
     * are new resources available for immediate use. */
    if (reslist->nidle > 0) {
        res = pop_resource(reslist);
        *resource = res->opaque;
        free_container(reslist, res);
        apr_thread_mutex_unlock(reslist->listlock);
        return APR_SUCCESS;
    }
    /* Otherwise the reason we dropped out of the loop
     * was because there is a new slot available, so create
     * a resource to fill the slot and use it. */
    else {
        rv = create_resource(reslist, &res);
        if (rv == APR_SUCCESS) {
            reslist->ntotal++;
            *resource = res->opaque;
        }
        free_container(reslist, res);
        apr_thread_mutex_unlock(reslist->listlock);
        return rv;
    }
}
示例#14
0
文件: h2_mplx.c 项目: Sp1l/mod_h2
apr_status_t h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait)
{
    apr_status_t status;
    int acquired;

    h2_workers_unregister(m->workers, m);
    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
        int i, wait_secs = 5;
        
        /* disable WINDOW_UPDATE callbacks */
        h2_mplx_set_consumed_cb(m, NULL, NULL);
        
        while (!h2_io_set_iter(m->stream_ios, stream_done_iter, m)) {
            /* iterate until all ios have been orphaned or destroyed */
        }
    
        /* Any remaining ios have handed out requests to workers that are
         * not done yet. Any operation they do on their assigned stream ios will
         * be errored ECONNRESET/ABORTED, so that should find out pretty soon.
         */
        for (i = 0; h2_io_set_size(m->stream_ios) > 0; ++i) {
            m->join_wait = wait;
            ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
                          "h2_mplx(%ld): release_join, waiting on %d worker to report back", 
                          m->id, (int)h2_io_set_size(m->stream_ios));
                          
            status = apr_thread_cond_timedwait(wait, m->lock, apr_time_from_sec(wait_secs));
            if (APR_STATUS_IS_TIMEUP(status)) {
                if (i > 0) {
                    /* Oh, oh. Still we wait for assigned  workers to report that 
                     * they are done. Unless we have a bug, a worker seems to be hanging. 
                     * If we exit now, all will be deallocated and the worker, once 
                     * it does return, will walk all over freed memory...
                     */
                    ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c,
                                  "h2_mplx(%ld): release, waiting for %d seconds now for "
                                  "all h2_workers to return, have still %d requests outstanding", 
                                  m->id, i*wait_secs, (int)h2_io_set_size(m->stream_ios));
                }
            }
        }
        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, m->c,
                      "h2_mplx(%ld): release_join -> destroy", m->id);
        leave_mutex(m, acquired);
        h2_mplx_destroy(m);
        /* all gone */
    }
    return status;
}
/** \brief Send MRCP request to client stack and wait for async response */
static apt_bool_t uni_recog_mrcp_request_send(uni_speech_t *uni_speech, mrcp_message_t *message)
{
	apt_bool_t res = FALSE;
	apr_thread_mutex_lock(uni_speech->mutex);
	uni_speech->mrcp_request = message;

	/* Send MRCP request */
	ast_log(LOG_DEBUG, "(%s) Send MRCP request method-id: %d\n",uni_speech->name,(int)message->start_line.method_id);
	res = mrcp_application_message_send(uni_speech->session,uni_speech->channel,message);
	if(res == TRUE) {
		/* Wait for MRCP response */
		ast_log(LOG_DEBUG, "(%s) Wait for MRCP response\n",uni_speech->name);
		if(apr_thread_cond_timedwait(uni_speech->wait_object,uni_speech->mutex,MRCP_APP_REQUEST_TIMEOUT) != APR_SUCCESS) {
			ast_log(LOG_ERROR, "(%s) Failed to get MRCP response: request timed out\n",uni_speech->name);
			uni_speech->mrcp_response = NULL;
		}

		/* Wake up and check received response */
		if(uni_speech->mrcp_response) {
			mrcp_message_t *mrcp_response = uni_speech->mrcp_response;
			ast_log(LOG_DEBUG, "(%s) Process MRCP response method-id: %d status-code: %d\n",
					uni_speech->name, 
					(int)mrcp_response->start_line.method_id,
					mrcp_response->start_line.status_code);
			
			if(mrcp_response->start_line.status_code != MRCP_STATUS_CODE_SUCCESS && 
				mrcp_response->start_line.status_code != MRCP_STATUS_CODE_SUCCESS_WITH_IGNORE) {
				ast_log(LOG_WARNING, "(%s) MRCP request failed method-id: %d status-code: %d\n",
						uni_speech->name,
						(int)mrcp_response->start_line.method_id,
						mrcp_response->start_line.status_code);
				res = FALSE;
			}
		}
		else {
			ast_log(LOG_ERROR, "(%s) No MRCP response available\n",uni_speech->name);
			res = FALSE;
		}
	}
	else {
		ast_log(LOG_WARNING, "(%s) Failed to send MRCP request\n",uni_speech->name);
	}
	uni_speech->mrcp_request = NULL;
	apr_thread_mutex_unlock(uni_speech->mutex);
	return res;
}
示例#16
0
/* Read from the audio queue. */
apr_status_t audio_queue_read(audio_queue_t *queue, void *data, apr_size_t *data_len, int block)
{
	apr_size_t requested;
	int status = 0;

	if ((queue == NULL) || (data == NULL) || (data_len == NULL))
		return -1;
	else
		requested = *data_len;

	if (queue->mutex != NULL)
		apr_thread_mutex_lock(queue->mutex);

	/* Wait for data, if allowed. */
	if (block != 0) {
		if (audio_buffer_inuse(queue->buffer) < requested) {
			queue->waiting = requested;

			if ((queue->mutex != NULL) && (queue->cond != NULL))
				apr_thread_cond_timedwait(queue->cond, queue->mutex, AUDIO_QUEUE_READ_TIMEOUT_USEC);

		}

		queue->waiting = 0;
	}

	if (audio_buffer_inuse(queue->buffer) < requested)
		requested = audio_buffer_inuse(queue->buffer);

	if (requested == 0) {
		*data_len = 0;
		status = -1;
	} else {
		/* Read the data. */
		*data_len = audio_buffer_read(queue->buffer, data, requested);
		queue->read_bytes = queue->read_bytes + *data_len;
	}

	if (queue->mutex != NULL)
		apr_thread_mutex_unlock(queue->mutex);

	return status;
}
示例#17
0
void *ds_ibp_warm_thread(apr_thread_t *th, void *data)
{
    data_service_fn_t *dsf = (data_service_fn_t *)data;
    ds_ibp_priv_t *ds = (ds_ibp_priv_t *)dsf->priv;
    apr_time_t max_wait;
    char *mcap;
    apr_ssize_t hlen;
    apr_hash_index_t *hi;
    ibp_capset_t *w;
    opque_t *q;
    int dt, err;

    dt = 60;
    max_wait = apr_time_make(ds->warm_interval, 0);
    apr_thread_mutex_lock(ds->lock);
    while (ds->warm_stop == 0) {
        //** Generate all the tasks
        log_printf(10, "Starting auto-warming run\n");

        q = new_opque();
        for (hi=apr_hash_first(NULL, ds->warm_table); hi != NULL; hi = apr_hash_next(hi)) {
            apr_hash_this(hi, (const void **)&mcap, &hlen, (void **)&w);
            opque_add(q, new_ibp_modify_alloc_op(ds->ic, mcap, -1, ds->warm_duration, -1, dt));
            log_printf(15, " warming: %s\n", mcap);

        }

        //** Wait until they all complete
        err = opque_waitall(q);
        log_printf(10, "opque_waitall=%d\n", err);

        opque_free(q, OP_DESTROY);  //** Clean up.  Don;t care if we are successfull or not:)

        //** Sleep until the next time or we get an exit request
        apr_thread_cond_timedwait(ds->cond, ds->lock, max_wait);
    }
    apr_thread_mutex_unlock(ds->lock);

    log_printf(10, "EXITING auto-warm thread\n");

    return(NULL);
}
示例#18
0
/** \brief Send session management request to client stack and wait for async response */
static apt_bool_t uni_recog_sm_request_send(uni_speech_t *uni_speech, mrcp_sig_command_e sm_request)
{
	apt_bool_t res = FALSE;
	ast_log(LOG_DEBUG, "Send session request type:%d\n",sm_request);
	apr_thread_mutex_lock(uni_speech->mutex);
	uni_speech->is_sm_request = TRUE;
	uni_speech->sm_request = sm_request;
	switch(sm_request) {
		case MRCP_SIG_COMMAND_SESSION_UPDATE:
			res = mrcp_application_session_update(uni_speech->session);
			break;
		case MRCP_SIG_COMMAND_SESSION_TERMINATE:
			res = mrcp_application_session_terminate(uni_speech->session);
			break;
		case MRCP_SIG_COMMAND_CHANNEL_ADD:
			res = mrcp_application_channel_add(uni_speech->session,uni_speech->channel);
			break;
		case MRCP_SIG_COMMAND_CHANNEL_REMOVE:
    			res = mrcp_application_channel_remove(uni_speech->session,uni_speech->channel);
			break;
		case MRCP_SIG_COMMAND_RESOURCE_DISCOVER:
    			res = mrcp_application_resource_discover(uni_speech->session);
			break;
		default:
			break;
	}

	if(res == TRUE) {
		/* Wait for session response */
		ast_log(LOG_DEBUG, "Wait for session response\n");
		if(apr_thread_cond_timedwait(uni_speech->wait_object,uni_speech->mutex,MRCP_APP_REQUEST_TIMEOUT) != APR_SUCCESS) {
		    ast_log(LOG_ERROR, "Failed to get response, request timed out\n");
		    uni_speech->sm_response = MRCP_SIG_STATUS_CODE_FAILURE;
		}
		ast_log(LOG_DEBUG, "Waked up, status code: %d\n",uni_speech->sm_response);
	}
	
	uni_speech->is_sm_request = FALSE;
	apr_thread_mutex_unlock(uni_speech->mutex);
	return res;
}
示例#19
0
apr_status_t h2_mplx_out_trywait(h2_mplx *m, apr_interval_time_t timeout,
                                 apr_thread_cond_t *iowait)
{
    AP_DEBUG_ASSERT(m);
    if (m->aborted) {
        return APR_ECONNABORTED;
    }
    apr_status_t status = apr_thread_mutex_lock(m->lock);
    if (APR_SUCCESS == status) {
        m->added_output = iowait;
        status = apr_thread_cond_timedwait(m->added_output, m->lock, timeout);
        if (APLOGctrace2(m->c)) {
            ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, m->c,
                          "h2_mplx(%ld): trywait on data for %f ms)",
                          m->id, timeout/1000.0);
        }
        m->added_output = NULL;
        apr_thread_mutex_unlock(m->lock);
    }
    return status;
}
示例#20
0
void *rss_check_thread(apr_thread_t *th, void *data)
{
    resource_service_fn_t *rs = (resource_service_fn_t *)data;
    rs_simple_priv_t *rss = (rs_simple_priv_t *)rs->priv;
    int do_notify, map_version, status_change;
    apr_interval_time_t dt;

    dt = apr_time_from_sec(rss->check_interval);

    apr_thread_mutex_lock(rss->lock);
    rss->current_check = 0;  //** Triggers a reload
    do {
        log_printf(5, "LOOP START\n");
        _rs_simple_refresh(rs);  //** Do a quick check and see if the file has changed

        do_notify = 0;
        if (rss->current_check != rss->modify_time) { //** Need to reload
            rss->current_check = rss->modify_time;
            do_notify = 1;
            // _rss_make_check_table(rs);
        }
        map_version = rss->modify_time;
        apr_thread_mutex_unlock(rss->lock);

        status_change = (rss->check_timeout <= 0) ? 0 : rss_perform_check(rs);

        if (((do_notify == 1) && (rss->dynamic_mapping == 1)) || (status_change != 0))  rss_mapping_notify(rs, map_version, status_change);

        log_printf(5, "LOOP END\n");

        apr_thread_mutex_lock(rss->lock);
        if (rss->shutdown == 0) apr_thread_cond_timedwait(rss->cond, rss->lock, dt);
    } while (rss->shutdown == 0);

    //** Clean up
    _rss_clear_check_table(rss->ds, rss->rid_mapping, rss->mpool);
    apr_thread_mutex_unlock(rss->lock);

    return(NULL);
}
示例#21
0
static void nested_lock_and_unlock(toolbox_t *box)
{
    apr_status_t rv;
    abts_case *tc = box->tc;

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

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

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

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

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

    rv = apr_thread_mutex_unlock(box->mutex);
    ABTS_SUCCESS(rv);
}
示例#22
0
/** \brief Send MRCP request to client stack and wait for async response */
static apt_bool_t uni_recog_mrcp_request_send(uni_speech_t *uni_speech, mrcp_message_t *message)
{
	apt_bool_t res = FALSE;
	apr_thread_mutex_lock(uni_speech->mutex);
	uni_speech->mrcp_request = message;

	/* Send MRCP request */
	ast_log(LOG_DEBUG, "Send MRCP request\n");
	res = mrcp_application_message_send(uni_speech->session,uni_speech->channel,message);

	if(res == TRUE) {
		/* Wait for MRCP response */
		ast_log(LOG_DEBUG, "Wait for MRCP response\n");
		if(apr_thread_cond_timedwait(uni_speech->wait_object,uni_speech->mutex,MRCP_APP_REQUEST_TIMEOUT) != APR_SUCCESS) {
		    ast_log(LOG_ERROR, "Failed to get response, request timed out\n");
		    uni_speech->mrcp_response = NULL;
		}
		ast_log(LOG_DEBUG, "Waked up\n");
	}
	uni_speech->mrcp_request = NULL;
	apr_thread_mutex_unlock(uni_speech->mutex);
	return res;
}
static void test_timeoutcond(abts_case *tc, void *data)
{
    apr_status_t s;
    apr_interval_time_t timeout;
    apr_time_t begin, end;
    int i;

    s = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT, p);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
    ABTS_PTR_NOTNULL(tc, timeout_mutex);

    s = apr_thread_cond_create(&timeout_cond, p);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
    ABTS_PTR_NOTNULL(tc, timeout_cond);

    timeout = apr_time_from_sec(5);

    for (i = 0; i < MAX_RETRY; i++) {
        apr_thread_mutex_lock(timeout_mutex);

        begin = apr_time_now();
        s = apr_thread_cond_timedwait(timeout_cond, timeout_mutex, timeout);
        end = apr_time_now();
        apr_thread_mutex_unlock(timeout_mutex);
        
        if (s != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(s)) {
            continue;
        }
        ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(s));
        ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 500000);
        break;
    }
    ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY);
    APR_ASSERT_SUCCESS(tc, "Unable to destroy the conditional",
                       apr_thread_cond_destroy(timeout_cond));
}
示例#24
0
void *ongoing_heartbeat_thread(apr_thread_t *th, void *data)
{
    mq_ongoing_t *on = (mq_ongoing_t *)data;
    apr_time_t timeout = apr_time_make(on->check_interval, 0);
    op_generic_t *gop;
    mq_msg_t *msg;
    ongoing_hb_t *oh;
    ongoing_table_t *table;
    apr_hash_index_t *hi, *hit;
    opque_t *q;
    char *id;
    mq_msg_hash_t *remote_hash;
    apr_time_t now;
    apr_ssize_t id_len;
    int n, k;
    char *remote_host_string;

    apr_thread_mutex_lock(on->lock);
    n = 0;
    do {
        now = apr_time_now() - apr_time_from_sec(5);  //** Give our selves a little buffer
        log_printf(5, "Loop Start now=" TT "\n", apr_time_now());
        q = new_opque();
//     opque_start_execution(q);
        for (hit = apr_hash_first(NULL, on->table); hit != NULL; hit = apr_hash_next(hit)) {
            apr_hash_this(hit, (const void **)&remote_hash, &id_len, (void **)&table);

            k = apr_hash_count(table->table);
            if (log_level() > 1) {
                remote_host_string = mq_address_to_string(table->remote_host);
                log_printf(1, "host=%s count=%d\n", remote_host_string, k);
                free(remote_host_string);
            }

            for (hi = apr_hash_first(NULL, table->table); hi != NULL; hi = apr_hash_next(hi)) {
                apr_hash_this(hi, (const void **)&id, &id_len, (void **)&oh);
                log_printf(1, "id=%s now=" TT " next_check=" TT "\n", oh->id, apr_time_sec(apr_time_now()), apr_time_sec(oh->next_check));
                if (now > oh->next_check) {
                    log_printf(1, "id=%s sending HEARTBEAT EXEC SUBMIT nows=" TT " hb=%d\n", oh->id, apr_time_sec(apr_time_now()), oh->heartbeat);
                    flush_log();
                    //** Form the message
                    msg = mq_make_exec_core_msg(table->remote_host, 1);
                    mq_msg_append_mem(msg, ONGOING_KEY, ONGOING_SIZE, MQF_MSG_KEEP_DATA);
                    mq_msg_append_mem(msg, oh->id, oh->id_len, MQF_MSG_KEEP_DATA);
                    mq_msg_append_mem(msg, NULL, 0, MQF_MSG_KEEP_DATA);

                    //** Make the gop
                    gop = new_mq_op(on->mqc, msg, ongoing_response_status, NULL, NULL, oh->heartbeat);
                    gop_set_private(gop, table);
                    opque_add(q, gop);

                    oh->in_progress = 1; //** Flag it as in progress so it doesn't get deleted behind the scenes
                }
            }

        }
        log_printf(5, "Loop end now=" TT "\n", apr_time_now());

        //** Wait for it to complete
        apr_thread_mutex_unlock(on->lock);
        opque_waitall(q);
        apr_thread_mutex_lock(on->lock);

        //** Dec the counters
        while ((gop = opque_waitany(q)) != NULL) {
            log_printf(0, "gid=%d gotone status=%d now=" TT "\n", gop_id(gop), (gop_get_status(gop)).op_status, apr_time_sec(apr_time_now()));
            table = gop_get_private(gop);
            table->count--;

            //** Update the next check
            for (hi = apr_hash_first(NULL, table->table); hi != NULL; hi = apr_hash_next(hi)) {
                apr_hash_this(hi, (const void **)&id, &id_len, (void **)&oh);
                oh->next_check = apr_time_now() + apr_time_from_sec(oh->heartbeat);

                //** Check if we get rid of it
                oh->in_progress = 0;
                if (oh->count <= 0) {  //** Need to delete it
                    apr_hash_set(table->table, id, id_len, NULL);
                    free(oh->id);
                    free(oh);
                }
            }

            gop_free(gop, OP_DESTROY);
        }
        opque_free(q, OP_DESTROY);

        now = apr_time_now();
        log_printf(2, "sleeping %d now=" TT "\n", on->check_interval, now);

        //** Sleep until time for the next heartbeat or time to exit
        if (on->shutdown == 0) apr_thread_cond_timedwait(on->cond, on->lock, timeout);
        n = on->shutdown;

        now = apr_time_now() - now;
        log_printf(2, "main loop bottom n=%d dt=" TT " sec=" TT "\n", n, now, apr_time_sec(now));
    } while (n == 0);

    log_printf(2, "CLEANUP\n");

    for (hit = apr_hash_first(NULL, on->table); hit != NULL; hit = apr_hash_next(hit)) {
        apr_hash_this(hit, (const void **)&remote_hash, &id_len, (void **)&table);

        for (hi = apr_hash_first(NULL, table->table); hi != NULL; hi = apr_hash_next(hi)) {
            apr_hash_this(hi, (const void **)&id, &id_len, (void **)&oh);
            apr_hash_set(table->table, id, id_len, NULL);
            free(oh->id);
            free(oh);
        }

        apr_hash_set(on->table, &(table->remote_host_hash), sizeof(mq_msg_hash_t), NULL);
        mq_msg_destroy(table->remote_host);
        free(table);
    }

    log_printf(2, "EXITING\n");

    apr_thread_mutex_unlock(on->lock);

    return(NULL);
}
示例#25
0
/* Send SPEAK request to synthesizer. */
static int synth_channel_speak(speech_channel_t *schannel, const char *content, const char *content_type, apr_hash_t *header_fields)
{
	int status = 0;
	mrcp_message_t *mrcp_message = NULL;
	mrcp_generic_header_t *generic_header = NULL;
	mrcp_synth_header_t *synth_header = NULL;

	if (!schannel || !content || !content_type) {
		ast_log(LOG_ERROR, "synth_channel_speak: unknown channel error!\n");
		return -1;
	}

	apr_thread_mutex_lock(schannel->mutex);

	if (schannel->state != SPEECH_CHANNEL_READY) {
		apr_thread_mutex_unlock(schannel->mutex);
		return -1;
	}

	if ((mrcp_message = mrcp_application_message_create(schannel->unimrcp_session, schannel->unimrcp_channel, SYNTHESIZER_SPEAK)) == NULL) {
		ast_log(LOG_ERROR, "(%s) Failed to create SPEAK message\n", schannel->name);

		apr_thread_mutex_unlock(schannel->mutex);
		return -1;
	}

	/* Set generic header fields (content-type). */
	if ((generic_header = (mrcp_generic_header_t *)mrcp_generic_header_prepare(mrcp_message)) == NULL) {	
		apr_thread_mutex_unlock(schannel->mutex);
		return -1;
	}

	apt_string_assign(&generic_header->content_type, content_type, mrcp_message->pool);
	mrcp_generic_header_property_add(mrcp_message, GENERIC_HEADER_CONTENT_TYPE);

	/* Set synthesizer header fields (voice, rate, etc.). */
	if ((synth_header = (mrcp_synth_header_t *)mrcp_resource_header_prepare(mrcp_message)) == NULL) {
		apr_thread_mutex_unlock(schannel->mutex);
		return -1;
	}

	/* Add params to MRCP message. */
	speech_channel_set_params(schannel, mrcp_message, header_fields);

	/* Set body (plain text or SSML). */
	apt_string_assign(&mrcp_message->body, content, schannel->pool);

	/* Empty audio queue and send SPEAK to MRCP server. */
	audio_queue_clear(schannel->audio_queue);

	if (!mrcp_application_message_send(schannel->unimrcp_session, schannel->unimrcp_channel, mrcp_message)) {
		ast_log(LOG_ERROR,"(%s) Failed to send SPEAK message", schannel->name);

		apr_thread_mutex_unlock(schannel->mutex);
		return -1;
	}

	/* Wait for IN PROGRESS. */
	apr_thread_cond_timedwait(schannel->cond, schannel->mutex, SPEECH_CHANNEL_TIMEOUT_USEC);

	if (schannel->state != SPEECH_CHANNEL_PROCESSING) {
		apr_thread_mutex_unlock(schannel->mutex);
		return -1;
	}

	apr_thread_mutex_unlock(schannel->mutex);
	return status;
}
示例#26
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;
}
示例#27
0
/** Initiate recognition based on specified grammar and input stream */
ASR_CLIENT_DECLARE(const char*) asr_session_stream_recognize(
									asr_session_t *asr_session,
									const char *grammar_file)
{
	const mrcp_app_message_t *app_message;
	mrcp_message_t *mrcp_message;

	app_message = NULL;
	mrcp_message = define_grammar_message_create(asr_session,grammar_file);
	if(!mrcp_message) {
		apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create DEFINE-GRAMMAR Request");
		return NULL;
	}

	/* Send DEFINE-GRAMMAR request and wait for the response */
	apr_thread_mutex_lock(asr_session->mutex);
	if(mrcp_application_message_send(asr_session->mrcp_session,asr_session->mrcp_channel,mrcp_message) == TRUE) {
		apr_thread_cond_wait(asr_session->wait_object,asr_session->mutex);
		app_message = asr_session->app_message;
		asr_session->app_message = NULL;
	}
	apr_thread_mutex_unlock(asr_session->mutex);

	if(mrcp_response_check(app_message,MRCP_REQUEST_STATE_COMPLETE) == FALSE) {
		return NULL;
	}

	/* Reset prev recog result (if any) */
	asr_session->recog_complete = NULL;

	app_message = NULL;
	mrcp_message = recognize_message_create(asr_session);
	if(!mrcp_message) {
		apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create RECOGNIZE Request");
		return NULL;
	}

	/* Send RECOGNIZE request and wait for the response */
	apr_thread_mutex_lock(asr_session->mutex);
	if(mrcp_application_message_send(asr_session->mrcp_session,asr_session->mrcp_channel,mrcp_message) == TRUE) {
		apr_thread_cond_wait(asr_session->wait_object,asr_session->mutex);
		app_message = asr_session->app_message;
		asr_session->app_message = NULL;
	}
	apr_thread_mutex_unlock(asr_session->mutex);

	if(mrcp_response_check(app_message,MRCP_REQUEST_STATE_INPROGRESS) == FALSE) {
		return NULL;
	}

	/* Reset media buffer */
	mpf_frame_buffer_restart(asr_session->media_buffer);
	
	/* Set input mode and start streaming */
	asr_session->input_mode = INPUT_MODE_STREAM;
	asr_session->streaming = TRUE;

	/* Wait for events either START-OF-INPUT or RECOGNITION-COMPLETE */
	do {
		apr_thread_mutex_lock(asr_session->mutex);
		app_message = NULL;
		if(apr_thread_cond_timedwait(asr_session->wait_object,asr_session->mutex, 60 * 1000000) != APR_SUCCESS) {
			apr_thread_mutex_unlock(asr_session->mutex);
			return NULL;
		}
		app_message = asr_session->app_message;
		asr_session->app_message = NULL;
		apr_thread_mutex_unlock(asr_session->mutex);

		mrcp_message = mrcp_event_get(app_message);
		if(mrcp_message && mrcp_message->start_line.method_id == RECOGNIZER_RECOGNITION_COMPLETE) {
			asr_session->recog_complete = mrcp_message;
		}
	}
	while(!asr_session->recog_complete);

	/* Get results */
	return nlsml_input_get(asr_session->recog_complete);
}
示例#28
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);
}
/*
 * The worker thread function. Take a task from the queue and perform it if
 * there is any. Otherwise, put itself into the idle thread list and waiting
 * for signal to wake up.
 * The thread terminate directly by detach and exit when it is asked to stop
 * after finishing a task. Otherwise, the thread should be in idle thread list
 * and should be joined.
 */
static void *APR_THREAD_FUNC thread_pool_func(apr_thread_t * t, void *param)
{
    apr_thread_pool_t *me = param;
    apr_thread_pool_task_t *task = NULL;
    apr_interval_time_t wait;
    struct apr_thread_list_elt *elt;

    apr_thread_mutex_lock(me->lock);

    --me->spawning_cnt;

    elt = elt_new(me, t);
    if (!elt) {
        apr_thread_mutex_unlock(me->lock);
        apr_thread_exit(t, APR_ENOMEM);
    }

    while (!me->terminated && elt->state != TH_STOP) {
        /* Test if not new element, it is awakened from idle */
        if (APR_RING_NEXT(elt, link) != elt) {
            --me->idle_cnt;
            APR_RING_REMOVE(elt, link);
        }

        APR_RING_INSERT_TAIL(me->busy_thds, elt, apr_thread_list_elt, link);
        task = pop_task(me);
        while (NULL != task && !me->terminated) {
            ++me->tasks_run;
            elt->current_owner = task->owner;
            apr_thread_mutex_unlock(me->lock);
            apr_thread_data_set(task, "apr_thread_pool_task", NULL, t);
            task->func(t, task->param);
            apr_thread_mutex_lock(me->lock);
            APR_RING_INSERT_TAIL(me->recycled_tasks, task,
                                 apr_thread_pool_task, link);
            elt->current_owner = NULL;
            if (TH_STOP == elt->state) {
                break;
            }
            task = pop_task(me);
        }
        assert(NULL == elt->current_owner);
        if (TH_STOP != elt->state)
            APR_RING_REMOVE(elt, link);

        /* Test if a busy thread been asked to stop, which is not joinable */
        if ((me->idle_cnt >= me->idle_max
             && !(me->scheduled_task_cnt && 0 >= me->idle_max)
             && !me->idle_wait)
            || me->terminated || elt->state != TH_RUN) {
            --me->thd_cnt;
            if ((TH_PROBATION == elt->state) && me->idle_wait)
                ++me->thd_timed_out;
            APR_RING_INSERT_TAIL(me->recycled_thds, elt,
                                 apr_thread_list_elt, link);
            apr_thread_mutex_unlock(me->lock);
            apr_thread_detach(t);
            apr_thread_exit(t, APR_SUCCESS);
            return NULL;        /* should not be here, safe net */
        }

        /* busy thread become idle */
        ++me->idle_cnt;
        APR_RING_INSERT_TAIL(me->idle_thds, elt, apr_thread_list_elt, link);

        /* 
         * If there is a scheduled task, always scheduled to perform that task.
         * Since there is no guarantee that current idle threads are scheduled
         * for next scheduled task.
         */
        if (me->scheduled_task_cnt)
            wait = waiting_time(me);
        else if (me->idle_cnt > me->idle_max) {
            wait = me->idle_wait;
            elt->state = TH_PROBATION;
        }
        else
            wait = -1;

        if (wait >= 0) {
            apr_thread_cond_timedwait(me->cond, me->lock, wait);
        }
        else {
            apr_thread_cond_wait(me->cond, me->lock);
        }
    }

    /* idle thread been asked to stop, will be joined */
    --me->thd_cnt;
    apr_thread_mutex_unlock(me->lock);
    apr_thread_exit(t, APR_SUCCESS);
    return NULL;                /* should not be here, safe net */
}
示例#30
0
int main(int argc, char **argv)
{
    int start_option, i, watch, summary, base;
    rs_mapping_notify_t notify, me;
    apr_time_t dt;
    char *config;

//printf("argc=%d\n", argc);

    if (argc < 2) {
        printf("\n");
        printf("lio_rs LIO_COMMON_OPTIONS [-w] [-b2 | -b10] [-s | -f]\n");
        lio_print_options(stdout);
        printf("    -w                 - Watch for RID configuration changes. Press ^C to exit\n");
        printf("    -b2                - Use powers of 2 for units(default)\n");
        printf("    -b10               - Use powers of 10 for units\n");
        printf("    -s                 - Print a RID space usage summary\n");
        printf("    -f                 - Print the full RID configuration\n");
        return(1);
    }

    lio_init(&argc, &argv);

    watch = 0;
    summary = 0;
    base = 1024;

    i=1;
    do {
        start_option = i;

        if (strcmp(argv[i], "-w") == 0) { //** Watch for any RID changes
            i++;
            watch = 1;
        } else if (strcmp(argv[i], "-s") == 0) {  //** Print space summary instead of full conifg
            i++;
            summary = 1;
        } else if (strcmp(argv[i], "-b2") == 0) {  //** base-2 units
            i++;
            base = 1024;
        } else if (strcmp(argv[i], "-b10") == 0) {  //** base-10 units
            i++;
            base = 1000;
        }
    } while ((start_option < i) && (i<argc));

    //** Make the APR stuff
    assert_result(apr_pool_create(&mpool, NULL), APR_SUCCESS);
    apr_thread_mutex_create(&lock, APR_THREAD_MUTEX_DEFAULT, mpool);
    apr_thread_cond_create(&cond, mpool);

//if (watch == 1) {
//  printf("Sleeping for 60s\n"); fflush(stdout);
//  sleep(60);
//  printf("Woken up\n"); fflush(stdout);
//}

    memset(&notify, 0, sizeof(notify));
    notify.lock = lock;
    notify.cond = cond;
    me = notify;
    me.map_version = 1; //** This triggers the initial load
    rs_register_mapping_updates(lio_gc->rs, &notify);
    dt = apr_time_from_sec(1);
    do {
        //** Check for an update
        apr_thread_mutex_lock(lock);
        if (watch == 1) apr_thread_cond_timedwait(notify.cond, notify.lock, dt);
        i = ((me.map_version != notify.map_version) || (me.status_version != notify.status_version)) ? 1 : 0;
        me = notify;
        apr_thread_mutex_unlock(lock);

        if (i != 0) {
            config = rs_get_rid_config(lio_gc->rs);

            printf("Map Version: %d  Status Version: %d\n", me.map_version, me.status_version);
            printf("--------------------------------------------------------------------------------------------------\n");

            if (config == NULL) {
                printf("ERROR NULL config!\n");
            } else if (summary == 1) {
                print_rid_summary(config, base);
            } else {
                printf("%s", config);
            }

            printf("--------------------------------------------------------------------------------------------------\n");

            if (config != NULL) free(config);
        }
    } while (watch == 1);

    info_printf(lio_ifd, 5, "BEFORE unregister\n");
    tbx_info_flush(lio_ifd);
    rs_unregister_mapping_updates(lio_gc->rs, &notify);
    info_printf(lio_ifd, 5, "AFTER unregister\n");
    tbx_info_flush(lio_ifd);

    //** Cleanup
    apr_pool_destroy(mpool);

//  info_printf(lio_ifd, 5, "AFTER shutdown\n"); tbx_info_flush(lio_ifd);
    lio_shutdown();

    return(0);
}