/* * OpenMRCP - Open Source Media Resource Control Protocol Stack * Copyright (C) 2007, Cepstral LLC * * Version: MPL 1.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * Author(s): * Arsen Chaloyan * * Contributor(s): * */ #include #include #include #include "apt_task.h" typedef struct apt_task_event_slot_t apt_task_event_slot_t; struct apt_task_event_slot_t { void *data; apt_task_event_handler handler; }; struct apt_task_t { apr_pool_t *pool; apr_thread_mutex_t *data_guard; apr_thread_t *thread_handle; apt_task_state_t state; apt_task_event_slot_t main; apt_task_event_slot_t event_handlers[TASK_STATE_COUNT]; }; static void* APR_THREAD_FUNC apt_task_run(apr_thread_t *thread_handle, void *data); static APR_INLINE void apt_task_event_raise(apt_task_t *task, apt_task_state_t task_event) { if(task->event_handlers[task_event].handler) { task->event_handlers[task_event].handler(task->event_handlers[task_event].data); } } APT_DECLARE(apt_task_t*) apt_task_create(void *data, apt_task_event_handler main, apr_pool_t *pool) { apr_size_t i; apt_task_t *task = apr_palloc(pool,sizeof(apt_task_t)); task->pool = pool; task->state = TASK_STATE_NONE; task->thread_handle = NULL; if(apr_thread_mutex_create(&task->data_guard, APR_THREAD_MUTEX_DEFAULT, task->pool) != APR_SUCCESS) { return NULL; } task->main.data = data; task->main.handler = main; for(i=0; ievent_handlers[i].data = NULL; task->event_handlers[i].handler = NULL; } return task; } APT_DECLARE(apt_bool_t) apt_task_destroy(apt_task_t *task) { apt_bool_t wait_until_terminate = FALSE; apr_thread_mutex_lock(task->data_guard); if(task->state != TASK_STATE_NONE) { wait_until_terminate = TRUE; } apr_thread_mutex_unlock(task->data_guard); if(wait_until_terminate == TRUE) { apt_task_wait_until_terminate(task); } apr_thread_mutex_destroy(task->data_guard); return TRUE; } APT_DECLARE(apt_bool_t) apt_task_start(apt_task_t *task) { apt_bool_t status = TRUE; apr_thread_mutex_lock(task->data_guard); if(task->state == TASK_STATE_NONE || task->state == TASK_STATE_TERMINATE_COMPLETED) { apr_status_t rv; task->state = TASK_STATE_START_REQUESTED; apt_task_event_raise(task,task->state); rv = apr_thread_create(&task->thread_handle,NULL,apt_task_run,task,task->pool); if(rv != APR_SUCCESS) { task->state = TASK_STATE_NONE; status = FALSE; } } else { status = FALSE; } apr_thread_mutex_unlock(task->data_guard); return status; } APT_DECLARE(apt_bool_t) apt_task_terminate(apt_task_t *task, apt_bool_t wait_until_terminate) { apr_thread_mutex_lock(task->data_guard); if(task->state == TASK_STATE_START_REQUESTED || task->state == TASK_STATE_START_IN_PROGRESS || task->state == TASK_STATE_START_COMPLETED) { task->state = TASK_STATE_TERMINATE_REQUESTED; } apr_thread_mutex_unlock(task->data_guard); if(task->state == TASK_STATE_TERMINATE_REQUESTED) { apt_task_event_raise(task,task->state); if(wait_until_terminate == TRUE) { apt_task_wait_until_terminate(task); } } return TRUE; } APT_DECLARE(apt_bool_t) apt_task_wait_until_terminate(apt_task_t *task) { if(task->thread_handle) { apr_status_t s; apr_thread_join(&s,task->thread_handle); } return TRUE; } APT_DECLARE(void) apt_task_delay(apr_size_t msec) { apr_sleep(1000*msec); } APT_DECLARE(apt_bool_t) apt_task_event_handler_set(apt_task_t *task, apt_task_state_t task_event, void *data, apt_task_event_handler handler) { if(task_event >= TASK_STATE_COUNT) { return FALSE; } task->event_handlers[task_event].data = data; task->event_handlers[task_event].handler = handler; return TRUE; } APT_DECLARE(apt_task_state_t) apt_task_state_set(apt_task_t *task, apt_task_state_t state) { task->state = state; apt_task_event_raise(task,task->state); return TRUE; } APT_DECLARE(apt_task_state_t) apt_task_state_get(apt_task_t *task) { return task->state; } APT_DECLARE(void*) apt_task_data_get(apt_task_t *task) { return task->main.data; } static void* APR_THREAD_FUNC apt_task_run(apr_thread_t *thread_handle, void *data) { apt_task_t *task = data; assert(task); apr_thread_mutex_lock(task->data_guard); task->state = TASK_STATE_START_IN_PROGRESS; apr_thread_mutex_unlock(task->data_guard); apt_task_event_raise(task,task->state); if(task->main.handler) { task->main.handler(task->main.data); } apr_thread_mutex_lock(task->data_guard); task->state = TASK_STATE_TERMINATE_COMPLETED; apr_thread_mutex_unlock(task->data_guard); apt_task_event_raise(task,task->state); apr_thread_mutex_lock(task->data_guard); task->state = TASK_STATE_NONE; apr_thread_mutex_unlock(task->data_guard); return NULL; }