diff options
Diffstat (limited to 'media/sphinxbase/src/libsphinxbase/util/sbthread.c')
-rw-r--r-- | media/sphinxbase/src/libsphinxbase/util/sbthread.c | 741 |
1 files changed, 0 insertions, 741 deletions
diff --git a/media/sphinxbase/src/libsphinxbase/util/sbthread.c b/media/sphinxbase/src/libsphinxbase/util/sbthread.c deleted file mode 100644 index 28bf773569..0000000000 --- a/media/sphinxbase/src/libsphinxbase/util/sbthread.c +++ /dev/null @@ -1,741 +0,0 @@ -/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* ==================================================================== - * Copyright (c) 2008 Carnegie Mellon University. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * This work was supported in part by funding from the Defense Advanced - * Research Projects Agency and the National Science Foundation of the - * United States of America, and the CMU Sphinx Speech Consortium. - * - * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY - * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ==================================================================== - * - */ - -/** - * @file sbthread.c - * @brief Simple portable thread functions - * @author David Huggins-Daines <dhuggins@cs.cmu.edu> - */ - -#include <string.h> - -#include "sphinxbase/sbthread.h" -#include "sphinxbase/ckd_alloc.h" -#include "sphinxbase/err.h" - -/* - * Platform-specific parts: threads, mutexes, and signals. - */ -#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(__SYMBIAN32__) -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0400 -#endif /* not _WIN32_WINNT */ -#include <windows.h> - -struct sbthread_s { - cmd_ln_t *config; - sbmsgq_t *msgq; - sbthread_main func; - void *arg; - HANDLE th; - DWORD tid; -}; - -struct sbmsgq_s { - /* Ringbuffer for passing messages. */ - char *data; - size_t depth; - size_t out; - size_t nbytes; - - /* Current message is stored here. */ - char *msg; - size_t msglen; - CRITICAL_SECTION mtx; - HANDLE evt; -}; - -struct sbevent_s { - HANDLE evt; -}; - -struct sbmtx_s { - CRITICAL_SECTION mtx; -}; - -DWORD WINAPI -sbthread_internal_main(LPVOID arg) -{ - sbthread_t *th = (sbthread_t *)arg; - int rv; - - rv = (*th->func)(th); - return (DWORD)rv; -} - -sbthread_t * -sbthread_start(cmd_ln_t *config, sbthread_main func, void *arg) -{ - sbthread_t *th; - - th = ckd_calloc(1, sizeof(*th)); - th->config = config; - th->func = func; - th->arg = arg; - th->msgq = sbmsgq_init(256); - th->th = CreateThread(NULL, 0, sbthread_internal_main, th, 0, &th->tid); - if (th->th == NULL) { - sbthread_free(th); - return NULL; - } - return th; -} - -int -sbthread_wait(sbthread_t *th) -{ - DWORD rv, exit; - - /* It has already been joined. */ - if (th->th == NULL) - return -1; - - rv = WaitForSingleObject(th->th, INFINITE); - if (rv == WAIT_FAILED) { - E_ERROR("Failed to join thread: WAIT_FAILED\n"); - return -1; - } - GetExitCodeThread(th->th, &exit); - CloseHandle(th->th); - th->th = NULL; - return (int)exit; -} - -static DWORD -cond_timed_wait(HANDLE cond, int sec, int nsec) -{ - DWORD rv; - if (sec == -1) { - rv = WaitForSingleObject(cond, INFINITE); - } - else { - DWORD ms; - - ms = sec * 1000 + nsec / (1000*1000); - rv = WaitForSingleObject(cond, ms); - } - return rv; -} - -/* Updated to use Unicode */ -sbevent_t * -sbevent_init(void) -{ - sbevent_t *evt; - - evt = ckd_calloc(1, sizeof(*evt)); - evt->evt = CreateEventW(NULL, FALSE, FALSE, NULL); - if (evt->evt == NULL) { - ckd_free(evt); - return NULL; - } - return evt; -} - -void -sbevent_free(sbevent_t *evt) -{ - CloseHandle(evt->evt); - ckd_free(evt); -} - -int -sbevent_signal(sbevent_t *evt) -{ - return SetEvent(evt->evt) ? 0 : -1; -} - -int -sbevent_wait(sbevent_t *evt, int sec, int nsec) -{ - DWORD rv; - - rv = cond_timed_wait(evt->evt, sec, nsec); - return rv; -} - -sbmtx_t * -sbmtx_init(void) -{ - sbmtx_t *mtx; - - mtx = ckd_calloc(1, sizeof(*mtx)); - InitializeCriticalSection(&mtx->mtx); - return mtx; -} - -int -sbmtx_trylock(sbmtx_t *mtx) -{ - return TryEnterCriticalSection(&mtx->mtx) ? 0 : -1; -} - -int -sbmtx_lock(sbmtx_t *mtx) -{ - EnterCriticalSection(&mtx->mtx); - return 0; -} - -int -sbmtx_unlock(sbmtx_t *mtx) -{ - LeaveCriticalSection(&mtx->mtx); - return 0; -} - -void -sbmtx_free(sbmtx_t *mtx) -{ - DeleteCriticalSection(&mtx->mtx); - ckd_free(mtx); -} - -sbmsgq_t * -sbmsgq_init(size_t depth) -{ - sbmsgq_t *msgq; - - msgq = ckd_calloc(1, sizeof(*msgq)); - msgq->depth = depth; - msgq->evt = CreateEventW(NULL, FALSE, FALSE, NULL); - if (msgq->evt == NULL) { - ckd_free(msgq); - return NULL; - } - InitializeCriticalSection(&msgq->mtx); - msgq->data = ckd_calloc(depth, 1); - msgq->msg = ckd_calloc(depth, 1); - return msgq; -} - -void -sbmsgq_free(sbmsgq_t *msgq) -{ - CloseHandle(msgq->evt); - ckd_free(msgq->data); - ckd_free(msgq->msg); - ckd_free(msgq); -} - -int -sbmsgq_send(sbmsgq_t *q, size_t len, void const *data) -{ - char const *cdata = (char const *)data; - size_t in; - - /* Don't allow things bigger than depth to be sent! */ - if (len + sizeof(len) > q->depth) - return -1; - - if (q->nbytes + len + sizeof(len) > q->depth) - WaitForSingleObject(q->evt, INFINITE); - - /* Lock things while we manipulate the buffer (FIXME: this - actually should have been atomic with the wait above ...) */ - EnterCriticalSection(&q->mtx); - in = (q->out + q->nbytes) % q->depth; - /* First write the size of the message. */ - if (in + sizeof(len) > q->depth) { - /* Handle the annoying case where the size field gets wrapped around. */ - size_t len1 = q->depth - in; - memcpy(q->data + in, &len, len1); - memcpy(q->data, ((char *)&len) + len1, sizeof(len) - len1); - q->nbytes += sizeof(len); - in = sizeof(len) - len1; - } - else { - memcpy(q->data + in, &len, sizeof(len)); - q->nbytes += sizeof(len); - in += sizeof(len); - } - - /* Now write the message body. */ - if (in + len > q->depth) { - /* Handle wraparound. */ - size_t len1 = q->depth - in; - memcpy(q->data + in, cdata, len1); - q->nbytes += len1; - cdata += len1; - len -= len1; - in = 0; - } - memcpy(q->data + in, cdata, len); - q->nbytes += len; - - /* Signal the condition variable. */ - SetEvent(q->evt); - /* Unlock. */ - LeaveCriticalSection(&q->mtx); - - return 0; -} - -void * -sbmsgq_wait(sbmsgq_t *q, size_t *out_len, int sec, int nsec) -{ - char *outptr; - size_t len; - - /* Wait for data to be available. */ - if (q->nbytes == 0) { - if (cond_timed_wait(q->evt, sec, nsec) == WAIT_FAILED) - /* Timed out or something... */ - return NULL; - } - /* Lock to manipulate the queue (FIXME) */ - EnterCriticalSection(&q->mtx); - /* Get the message size. */ - if (q->out + sizeof(q->msglen) > q->depth) { - /* Handle annoying wraparound case. */ - size_t len1 = q->depth - q->out; - memcpy(&q->msglen, q->data + q->out, len1); - memcpy(((char *)&q->msglen) + len1, q->data, - sizeof(q->msglen) - len1); - q->out = sizeof(q->msglen) - len1; - } - else { - memcpy(&q->msglen, q->data + q->out, sizeof(q->msglen)); - q->out += sizeof(q->msglen); - } - q->nbytes -= sizeof(q->msglen); - /* Get the message body. */ - outptr = q->msg; - len = q->msglen; - if (q->out + q->msglen > q->depth) { - /* Handle wraparound. */ - size_t len1 = q->depth - q->out; - memcpy(outptr, q->data + q->out, len1); - outptr += len1; - len -= len1; - q->nbytes -= len1; - q->out = 0; - } - memcpy(outptr, q->data + q->out, len); - q->nbytes -= len; - q->out += len; - - /* Signal the condition variable. */ - SetEvent(q->evt); - /* Unlock. */ - LeaveCriticalSection(&q->mtx); - if (out_len) - *out_len = q->msglen; - return q->msg; -} - -#else /* POSIX */ -#include <pthread.h> -#include <sys/time.h> - -struct sbthread_s { - cmd_ln_t *config; - sbmsgq_t *msgq; - sbthread_main func; - void *arg; - pthread_t th; -}; - -struct sbmsgq_s { - /* Ringbuffer for passing messages. */ - char *data; - size_t depth; - size_t out; - size_t nbytes; - - /* Current message is stored here. */ - char *msg; - size_t msglen; - pthread_mutex_t mtx; - pthread_cond_t cond; -}; - -struct sbevent_s { - pthread_mutex_t mtx; - pthread_cond_t cond; - int signalled; -}; - -struct sbmtx_s { - pthread_mutex_t mtx; -}; - -static void * -sbthread_internal_main(void *arg) -{ - sbthread_t *th = (sbthread_t *)arg; - int rv; - - rv = (*th->func)(th); - return (void *)(long)rv; -} - -sbthread_t * -sbthread_start(cmd_ln_t *config, sbthread_main func, void *arg) -{ - sbthread_t *th; - int rv; - - th = ckd_calloc(1, sizeof(*th)); - th->config = config; - th->func = func; - th->arg = arg; - th->msgq = sbmsgq_init(1024); - if ((rv = pthread_create(&th->th, NULL, &sbthread_internal_main, th)) != 0) { - E_ERROR("Failed to create thread: %d\n", rv); - sbthread_free(th); - return NULL; - } - return th; -} - -int -sbthread_wait(sbthread_t *th) -{ - void *exit; - int rv; - - /* It has already been joined. */ - if (th->th == (pthread_t)-1) - return -1; - - rv = pthread_join(th->th, &exit); - if (rv != 0) { - E_ERROR("Failed to join thread: %d\n", rv); - return -1; - } - th->th = (pthread_t)-1; - return (int)(long)exit; -} - -sbmsgq_t * -sbmsgq_init(size_t depth) -{ - sbmsgq_t *msgq; - - msgq = ckd_calloc(1, sizeof(*msgq)); - msgq->depth = depth; - if (pthread_cond_init(&msgq->cond, NULL) != 0) { - ckd_free(msgq); - return NULL; - } - if (pthread_mutex_init(&msgq->mtx, NULL) != 0) { - pthread_cond_destroy(&msgq->cond); - ckd_free(msgq); - return NULL; - } - msgq->data = ckd_calloc(depth, 1); - msgq->msg = ckd_calloc(depth, 1); - return msgq; -} - -void -sbmsgq_free(sbmsgq_t *msgq) -{ - pthread_mutex_destroy(&msgq->mtx); - pthread_cond_destroy(&msgq->cond); - ckd_free(msgq->data); - ckd_free(msgq->msg); - ckd_free(msgq); -} - -int -sbmsgq_send(sbmsgq_t *q, size_t len, void const *data) -{ - size_t in; - - /* Don't allow things bigger than depth to be sent! */ - if (len + sizeof(len) > q->depth) - return -1; - - /* Lock the condition variable while we manipulate the buffer. */ - pthread_mutex_lock(&q->mtx); - if (q->nbytes + len + sizeof(len) > q->depth) { - /* Unlock and wait for space to be available. */ - if (pthread_cond_wait(&q->cond, &q->mtx) != 0) { - /* Timed out, don't send anything. */ - pthread_mutex_unlock(&q->mtx); - return -1; - } - /* Condition is now locked again. */ - } - in = (q->out + q->nbytes) % q->depth; - - /* First write the size of the message. */ - if (in + sizeof(len) > q->depth) { - /* Handle the annoying case where the size field gets wrapped around. */ - size_t len1 = q->depth - in; - memcpy(q->data + in, &len, len1); - memcpy(q->data, ((char *)&len) + len1, sizeof(len) - len1); - q->nbytes += sizeof(len); - in = sizeof(len) - len1; - } - else { - memcpy(q->data + in, &len, sizeof(len)); - q->nbytes += sizeof(len); - in += sizeof(len); - } - - /* Now write the message body. */ - if (in + len > q->depth) { - /* Handle wraparound. */ - size_t len1 = q->depth - in; - memcpy(q->data + in, data, len1); - q->nbytes += len1; - data = (char const *)data + len1; - len -= len1; - in = 0; - } - memcpy(q->data + in, data, len); - q->nbytes += len; - - /* Signal the condition variable. */ - pthread_cond_signal(&q->cond); - /* Unlock it, we have nothing else to do. */ - pthread_mutex_unlock(&q->mtx); - return 0; -} - -static int -cond_timed_wait(pthread_cond_t *cond, pthread_mutex_t *mtx, int sec, int nsec) -{ - int rv; - if (sec == -1) { - rv = pthread_cond_wait(cond, mtx); - } - else { - struct timeval now; - struct timespec end; - - gettimeofday(&now, NULL); - end.tv_sec = now.tv_sec + sec; - end.tv_nsec = now.tv_usec * 1000 + nsec; - if (end.tv_nsec > (1000*1000*1000)) { - sec += end.tv_nsec / (1000*1000*1000); - end.tv_nsec = end.tv_nsec % (1000*1000*1000); - } - rv = pthread_cond_timedwait(cond, mtx, &end); - } - return rv; -} - -void * -sbmsgq_wait(sbmsgq_t *q, size_t *out_len, int sec, int nsec) -{ - char *outptr; - size_t len; - - /* Lock the condition variable while we manipulate nmsg. */ - pthread_mutex_lock(&q->mtx); - if (q->nbytes == 0) { - /* Unlock the condition variable and wait for a signal. */ - if (cond_timed_wait(&q->cond, &q->mtx, sec, nsec) != 0) { - /* Timed out or something... */ - pthread_mutex_unlock(&q->mtx); - return NULL; - } - /* Condition variable is now locked again. */ - } - /* Get the message size. */ - if (q->out + sizeof(q->msglen) > q->depth) { - /* Handle annoying wraparound case. */ - size_t len1 = q->depth - q->out; - memcpy(&q->msglen, q->data + q->out, len1); - memcpy(((char *)&q->msglen) + len1, q->data, - sizeof(q->msglen) - len1); - q->out = sizeof(q->msglen) - len1; - } - else { - memcpy(&q->msglen, q->data + q->out, sizeof(q->msglen)); - q->out += sizeof(q->msglen); - } - q->nbytes -= sizeof(q->msglen); - /* Get the message body. */ - outptr = q->msg; - len = q->msglen; - if (q->out + q->msglen > q->depth) { - /* Handle wraparound. */ - size_t len1 = q->depth - q->out; - memcpy(outptr, q->data + q->out, len1); - outptr += len1; - len -= len1; - q->nbytes -= len1; - q->out = 0; - } - memcpy(outptr, q->data + q->out, len); - q->nbytes -= len; - q->out += len; - - /* Signal the condition variable. */ - pthread_cond_signal(&q->cond); - /* Unlock the condition variable, we are done. */ - pthread_mutex_unlock(&q->mtx); - if (out_len) - *out_len = q->msglen; - return q->msg; -} - -sbevent_t * -sbevent_init(void) -{ - sbevent_t *evt; - int rv; - - evt = ckd_calloc(1, sizeof(*evt)); - if ((rv = pthread_mutex_init(&evt->mtx, NULL)) != 0) { - E_ERROR("Failed to initialize mutex: %d\n", rv); - ckd_free(evt); - return NULL; - } - if ((rv = pthread_cond_init(&evt->cond, NULL)) != 0) { - E_ERROR_SYSTEM("Failed to initialize mutex: %d\n", rv); - pthread_mutex_destroy(&evt->mtx); - ckd_free(evt); - return NULL; - } - return evt; -} - -void -sbevent_free(sbevent_t *evt) -{ - pthread_mutex_destroy(&evt->mtx); - pthread_cond_destroy(&evt->cond); - ckd_free(evt); -} - -int -sbevent_signal(sbevent_t *evt) -{ - int rv; - - pthread_mutex_lock(&evt->mtx); - evt->signalled = TRUE; - rv = pthread_cond_signal(&evt->cond); - pthread_mutex_unlock(&evt->mtx); - return rv; -} - -int -sbevent_wait(sbevent_t *evt, int sec, int nsec) -{ - int rv = 0; - - /* Lock the mutex before we check its signalled state. */ - pthread_mutex_lock(&evt->mtx); - /* If it's not signalled, then wait until it is. */ - if (!evt->signalled) - rv = cond_timed_wait(&evt->cond, &evt->mtx, sec, nsec); - /* Set its state to unsignalled if we were successful. */ - if (rv == 0) - evt->signalled = FALSE; - /* And unlock its mutex. */ - pthread_mutex_unlock(&evt->mtx); - - return rv; -} - -sbmtx_t * -sbmtx_init(void) -{ - sbmtx_t *mtx; - - mtx = ckd_calloc(1, sizeof(*mtx)); - if (pthread_mutex_init(&mtx->mtx, NULL) != 0) { - ckd_free(mtx); - return NULL; - } - return mtx; -} - -int -sbmtx_trylock(sbmtx_t *mtx) -{ - return pthread_mutex_trylock(&mtx->mtx); -} - -int -sbmtx_lock(sbmtx_t *mtx) -{ - return pthread_mutex_lock(&mtx->mtx); -} - -int -sbmtx_unlock(sbmtx_t *mtx) -{ - return pthread_mutex_unlock(&mtx->mtx); -} - -void -sbmtx_free(sbmtx_t *mtx) -{ - pthread_mutex_destroy(&mtx->mtx); - ckd_free(mtx); -} -#endif /* not WIN32 */ - -cmd_ln_t * -sbthread_config(sbthread_t *th) -{ - return th->config; -} - -void * -sbthread_arg(sbthread_t *th) -{ - return th->arg; -} - -sbmsgq_t * -sbthread_msgq(sbthread_t *th) -{ - return th->msgq; -} - -int -sbthread_send(sbthread_t *th, size_t len, void const *data) -{ - return sbmsgq_send(th->msgq, len, data); -} - -void -sbthread_free(sbthread_t *th) -{ - sbthread_wait(th); - sbmsgq_free(th->msgq); - ckd_free(th); -} |