📄 threads.c
字号:
/***************************************************************************** * threads.c : threads implementation for the VideoLAN client ***************************************************************************** * Copyright (C) 1999-2004 VideoLAN * $Id: threads.c 10706 2005-04-16 12:30:45Z courmisch $ * * Authors: Jean-Marc Dressler <polux@via.ecp.fr> * Samuel Hocevar <sam@zoy.org> * Gildas Bazin <gbazin@netcourrier.com> * * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/#include <vlc/vlc.h>#include <stdlib.h>#define VLC_THREADS_UNINITIALIZED 0#define VLC_THREADS_PENDING 1#define VLC_THREADS_ERROR 2#define VLC_THREADS_READY 3/***************************************************************************** * Global mutex for lazy initialization of the threads system *****************************************************************************/static volatile unsigned i_initializations = 0;static volatile int i_status = VLC_THREADS_UNINITIALIZED;static vlc_object_t *p_root;#if defined( PTH_INIT_IN_PTH_H )#elif defined( ST_INIT_IN_ST_H )#elif defined( UNDER_CE )#elif defined( WIN32 )#elif defined( HAVE_KERNEL_SCHEDULER_H )#elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) static pthread_mutex_t once_mutex = PTHREAD_MUTEX_INITIALIZER;#elif defined( HAVE_CTHREADS_H )#endif/***************************************************************************** * Global variable for named mutexes *****************************************************************************/typedef struct vlc_namedmutex_t vlc_namedmutex_t;struct vlc_namedmutex_t{ vlc_mutex_t lock; char *psz_name; int i_usage; vlc_namedmutex_t *p_next;};/***************************************************************************** * vlc_threads_init: initialize threads system ***************************************************************************** * This function requires lazy initialization of a global lock in order to * keep the library really thread-safe. Some architectures don't support this * and thus do not guarantee the complete reentrancy. *****************************************************************************/int __vlc_threads_init( vlc_object_t *p_this ){ libvlc_t *p_libvlc = (libvlc_t *)p_this; int i_ret = VLC_SUCCESS; /* If we have lazy mutex initialization, use it. Otherwise, we just * hope nothing wrong happens. */#if defined( PTH_INIT_IN_PTH_H )#elif defined( ST_INIT_IN_ST_H )#elif defined( UNDER_CE )#elif defined( WIN32 )#elif defined( HAVE_KERNEL_SCHEDULER_H )#elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) pthread_mutex_lock( &once_mutex );#elif defined( HAVE_CTHREADS_H )#endif if( i_status == VLC_THREADS_UNINITIALIZED ) { i_status = VLC_THREADS_PENDING; /* We should be safe now. Do all the initialization stuff we want. */ p_libvlc->b_ready = VLC_FALSE;#if defined( PTH_INIT_IN_PTH_H ) i_ret = ( pth_init() == FALSE );#elif defined( ST_INIT_IN_ST_H ) i_ret = st_init();#elif defined( UNDER_CE ) /* Nothing to initialize */#elif defined( WIN32 ) /* Dynamically get the address of SignalObjectAndWait */ if( GetVersion() < 0x80000000 ) { HINSTANCE hInstLib; /* We are running on NT/2K/XP, we can use SignalObjectAndWait */ hInstLib = LoadLibrary( "kernel32" ); if( hInstLib ) { p_libvlc->SignalObjectAndWait = (SIGNALOBJECTANDWAIT)GetProcAddress( hInstLib, "SignalObjectAndWait" ); } } else { p_libvlc->SignalObjectAndWait = NULL; } p_libvlc->b_fast_mutex = 0; p_libvlc->i_win9x_cv = 0;#elif defined( HAVE_KERNEL_SCHEDULER_H )#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )#elif defined( HAVE_CTHREADS_H )#endif p_root = vlc_object_create( p_libvlc, VLC_OBJECT_ROOT ); if( p_root == NULL ) i_ret = VLC_ENOMEM; if( i_ret ) { i_status = VLC_THREADS_ERROR; } else { i_initializations++; i_status = VLC_THREADS_READY; } } else { /* Just increment the initialization count */ i_initializations++; } /* If we have lazy mutex initialization support, unlock the mutex; * otherwize, do a naive wait loop. */#if defined( PTH_INIT_IN_PTH_H ) while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );#elif defined( ST_INIT_IN_ST_H ) while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );#elif defined( UNDER_CE ) while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );#elif defined( WIN32 ) while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );#elif defined( HAVE_KERNEL_SCHEDULER_H ) while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );#elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) pthread_mutex_unlock( &once_mutex );#elif defined( HAVE_CTHREADS_H ) while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );#endif if( i_status != VLC_THREADS_READY ) { return VLC_ETHREAD; } return i_ret;}/***************************************************************************** * vlc_threads_end: stop threads system ***************************************************************************** * FIXME: This function is far from being threadsafe. *****************************************************************************/int __vlc_threads_end( vlc_object_t *p_this ){#if defined( PTH_INIT_IN_PTH_H )#elif defined( ST_INIT_IN_ST_H )#elif defined( UNDER_CE )#elif defined( WIN32 )#elif defined( HAVE_KERNEL_SCHEDULER_H )#elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) pthread_mutex_lock( &once_mutex );#elif defined( HAVE_CTHREADS_H )#endif if( i_initializations == 0 ) return VLC_EGENERIC; i_initializations--; if( i_initializations == 0 ) { i_status = VLC_THREADS_UNINITIALIZED; vlc_object_destroy( p_root ); }#if defined( PTH_INIT_IN_PTH_H ) if( i_initializations == 0 ) { return ( pth_kill() == FALSE ); }#elif defined( ST_INIT_IN_ST_H )#elif defined( UNDER_CE )#elif defined( WIN32 )#elif defined( HAVE_KERNEL_SCHEDULER_H )#elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) pthread_mutex_unlock( &once_mutex );#elif defined( HAVE_CTHREADS_H )#endif return VLC_SUCCESS;}/***************************************************************************** * vlc_mutex_init: initialize a mutex *****************************************************************************/int __vlc_mutex_init( vlc_object_t *p_this, vlc_mutex_t *p_mutex ){ p_mutex->p_this = p_this;#if defined( PTH_INIT_IN_PTH_H ) return ( pth_mutex_init( &p_mutex->mutex ) == FALSE );#elif defined( ST_INIT_IN_ST_H ) p_mutex->mutex = st_mutex_new(); return ( p_mutex->mutex == NULL ) ? errno : 0;#elif defined( UNDER_CE ) InitializeCriticalSection( &p_mutex->csection ); return 0;#elif defined( WIN32 ) /* We use mutexes on WinNT/2K/XP because we can use the SignalObjectAndWait * function and have a 100% correct vlc_cond_wait() implementation. * As this function is not available on Win9x, we can use the faster * CriticalSections */ if( p_this->p_libvlc->SignalObjectAndWait && !p_this->p_libvlc->b_fast_mutex ) { /* We are running on NT/2K/XP, we can use SignalObjectAndWait */ p_mutex->mutex = CreateMutex( 0, FALSE, 0 ); return ( p_mutex->mutex != NULL ? 0 : 1 ); } else { p_mutex->mutex = NULL; InitializeCriticalSection( &p_mutex->csection ); return 0; }#elif defined( HAVE_KERNEL_SCHEDULER_H ) /* check the arguments and whether it's already been initialized */ if( p_mutex == NULL ) { return B_BAD_VALUE; } if( p_mutex->init == 9999 ) { return EALREADY; } p_mutex->lock = create_sem( 1, "BeMutex" ); if( p_mutex->lock < B_NO_ERROR ) { return( -1 ); } p_mutex->init = 9999; return B_OK;#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )# if defined(DEBUG) && defined(SYS_LINUX) { /* Create error-checking mutex to detect problems more easily. */ pthread_mutexattr_t attr; int i_result; pthread_mutexattr_init( &attr ); pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP ); i_result = pthread_mutex_init( &p_mutex->mutex, &attr ); pthread_mutexattr_destroy( &attr ); return( i_result ); }# endif return pthread_mutex_init( &p_mutex->mutex, NULL );#elif defined( HAVE_CTHREADS_H ) mutex_init( p_mutex ); return 0;#endif}/***************************************************************************** * vlc_mutex_destroy: destroy a mutex, inner version *****************************************************************************/int __vlc_mutex_destroy( char * psz_file, int i_line, vlc_mutex_t *p_mutex ){ int i_result; /* In case of error : */ int i_thread = -1; const char * psz_error = "";#if defined( PTH_INIT_IN_PTH_H ) return 0;#elif defined( ST_INIT_IN_ST_H ) i_result = st_mutex_destroy( p_mutex->mutex );#elif defined( UNDER_CE ) DeleteCriticalSection( &p_mutex->csection ); return 0;#elif defined( WIN32 ) if( p_mutex->mutex ) { CloseHandle( p_mutex->mutex ); } else { DeleteCriticalSection( &p_mutex->csection ); } return 0;#elif defined( HAVE_KERNEL_SCHEDULER_H ) if( p_mutex->init == 9999 ) { delete_sem( p_mutex->lock ); } p_mutex->init = 0; return B_OK;#elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) i_result = pthread_mutex_destroy( &p_mutex->mutex ); if ( i_result ) { i_thread = (int)pthread_self(); psz_error = strerror(i_result); }#elif defined( HAVE_CTHREADS_H ) return 0;#endif if( i_result ) { msg_Err( p_mutex->p_this, "thread %d: mutex_destroy failed at %s:%d (%d:%s)", i_thread, psz_file, i_line, i_result, psz_error ); } return i_result;}/***************************************************************************** * vlc_cond_init: initialize a condition *****************************************************************************/int __vlc_cond_init( vlc_object_t *p_this, vlc_cond_t *p_condvar ){ p_condvar->p_this = p_this;#if defined( PTH_INIT_IN_PTH_H ) return ( pth_cond_init( &p_condvar->cond ) == FALSE );#elif defined( ST_INIT_IN_ST_H ) p_condvar->cond = st_cond_new(); return ( p_condvar->cond == NULL ) ? errno : 0;#elif defined( UNDER_CE ) /* Initialize counter */ p_condvar->i_waiting_threads = 0; /* Create an auto-reset event. */ p_condvar->event = CreateEvent( NULL, /* no security */ FALSE, /* auto-reset event */ FALSE, /* start non-signaled */ NULL ); /* unnamed */ return !p_condvar->event;#elif defined( WIN32 ) /* Initialize counter */ p_condvar->i_waiting_threads = 0; /* Misc init */ p_condvar->i_win9x_cv = p_this->p_libvlc->i_win9x_cv; p_condvar->SignalObjectAndWait = p_this->p_libvlc->SignalObjectAndWait;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -