/* * bronx_thread.c -- Thread functionality. * * Copyright (C) 2007 Groundwork Open Source * Written by Daniel Emmanuel Feinsmith * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301, USA. * * Change Log: * DEF Created on September 17, 2007, 1:00 PM */ #include "bronx.h" /* * Globals. */ int _threads_running = FALSE; apr_thread_mutex_t *_threads_status_mutex; apr_thread_t *_thread_router, *_thread_listener; apr_pool_t *_thread_pool; /* * Externals. */ extern void* APR_THREAD_FUNC thread_router(apr_thread_t *, void *); extern void* APR_THREAD_FUNC thread_listener(apr_thread_t *, void *); extern void* APR_THREAD_FUNC thread_listener_processor(apr_thread_t *, void *); /* * Initialize thread system. */ int threads_running() { int rv; //apr_thread_mutex_lock(_threads_status_mutex); rv = _threads_running; //apr_thread_mutex_unlock(_threads_status_mutex); return(rv); } void set_threads_running(int s) { //apr_thread_mutex_lock(_threads_status_mutex); _threads_running = s; //apr_thread_mutex_unlock(_threads_status_mutex); } apr_status_t threads_init() { apr_status_t rv; _threads_running = FALSE; if ((rv=apr_pool_create(&_thread_pool, NULL)) != APR_SUCCESS) bronx_log("{threads_init} Failed to create thread pool.", BRONX_LOGGING_NORMAL); else if ((rv=apr_thread_mutex_create(&_threads_status_mutex, APR_THREAD_MUTEX_DEFAULT, _thread_pool)) != APR_SUCCESS) bronx_log("{threads_init} Failed to create thread mutex.", BRONX_LOGGING_NORMAL); return(rv); } void threads_uninit() { _threads_running = FALSE; apr_pool_destroy(_thread_pool); } /* * Start all relevant threads. */ int threads_start(configuration_criteria *config) { bronx_log("{threads_start} Starting Threads.", BRONX_LOGGING_NORMAL); if (!threads_running()) { apr_status_t result; /* * First, create router thread. */ result = apr_thread_create(&_thread_router, NULL, thread_router, NULL, _thread_pool); if(result == APR_SUCCESS) bronx_log("{threads_start} Created Router Thread.", BRONX_LOGGING_NORMAL); else { bronx_log("{threads_start} Failed to create router thread.", BRONX_LOGGING_NORMAL); return(FALSE); } /* * Next, if the user has specified a listener, * then create the listener thread. * * TODO: In the future, we need the capacity to create several * listeners, potentially of different kinds. Right now, * the listener is a nsca-type listener. We will certainly * need other kinds of listeners as time goes on, whether * they be tap-in, perhaps nscafe, and certainly * bronx. Not to mention a listener to handle things * like administrative commands, etc... */ if (config->listener) { result = apr_thread_create(&_thread_listener, NULL, thread_listener, NULL, _thread_pool); if(result == APR_SUCCESS) bronx_log("{threads_start} Created main listener thread.",BRONX_LOGGING_NORMAL); else { bronx_log("{threads_start} FAILED to create main listener thread.", BRONX_LOGGING_NORMAL); return(FALSE); } } bronx_log("{threads_start} Threads Initialization Completed.", BRONX_LOGGING_NORMAL); set_threads_running(TRUE); } return(threads_running()); } /* * Stop all relevant threads. */ int threads_stop(configuration_criteria *config) { if (threads_running()) { apr_status_t retval; apr_thread_join(&retval, _thread_router); apr_thread_join(&retval, _thread_listener); } return(1); } /* * Make sure the thread system is running. */ void assert_threads_running(configuration_criteria *config) { if (!threads_running()) threads_start(config); }