vlc_threads.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * vlc_threads.h : threads implementation for the VideoLAN client
00003  * This header provides portable declarations for mutexes & conditions
00004  *****************************************************************************
00005  * Copyright (C) 1999, 2002 the VideoLAN team
00006  * Copyright © 2007-2008 Rémi Denis-Courmont
00007  *
00008  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
00009  *          Samuel Hocevar <sam@via.ecp.fr>
00010  *          Gildas Bazin <gbazin@netcourrier.com>
00011  *          Christophe Massiot <massiot@via.ecp.fr>
00012  *
00013  * This program is free software; you can redistribute it and/or modify
00014  * it under the terms of the GNU General Public License as published by
00015  * the Free Software Foundation; either version 2 of the License, or
00016  * (at your option) any later version.
00017  *
00018  * This program is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License
00024  * along with this program; if not, write to the Free Software
00025  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
00026  *****************************************************************************/
00027 
00028 #ifndef VLC_THREADS_H_
00029 #define VLC_THREADS_H_
00030 
00031 /**
00032  * \file
00033  * This file defines structures and functions for handling threads in vlc
00034  *
00035  */
00036 
00037 #if defined( UNDER_CE )
00038 #elif defined( WIN32 )
00039 #   include <process.h>                                         /* Win32 API */
00040 
00041 #else                                         /* pthreads (like Linux & BSD) */
00042 #   define LIBVLC_USE_PTHREAD 1
00043 #   define LIBVLC_USE_PTHREAD_CANCEL 1
00044 #   define _APPLE_C_SOURCE    1 /* Proper pthread semantics on OSX */
00045 
00046 #   include <unistd.h> /* _POSIX_SPIN_LOCKS */
00047 #   include <pthread.h>
00048 
00049 /* Unnamed POSIX semaphores not supported on Mac OS X, use Mach semaphores instead */
00050 #   if defined (__APPLE__)
00051 #      include <mach/semaphore.h>
00052 #      include <mach/task.h>
00053 #   else
00054 #      include <semaphore.h>
00055 #   endif
00056 
00057 #endif
00058 
00059 /*****************************************************************************
00060  * Constants
00061  *****************************************************************************/
00062 
00063 /* Thread priorities */
00064 #ifdef __APPLE__
00065 #   define VLC_THREAD_PRIORITY_LOW      0
00066 #   define VLC_THREAD_PRIORITY_INPUT   22
00067 #   define VLC_THREAD_PRIORITY_AUDIO   22
00068 #   define VLC_THREAD_PRIORITY_VIDEO    0
00069 #   define VLC_THREAD_PRIORITY_OUTPUT  22
00070 #   define VLC_THREAD_PRIORITY_HIGHEST 22
00071 
00072 #elif defined(LIBVLC_USE_PTHREAD)
00073 #   define VLC_THREAD_PRIORITY_LOW      0
00074 #   define VLC_THREAD_PRIORITY_INPUT   10
00075 #   define VLC_THREAD_PRIORITY_AUDIO    5
00076 #   define VLC_THREAD_PRIORITY_VIDEO    0
00077 #   define VLC_THREAD_PRIORITY_OUTPUT  15
00078 #   define VLC_THREAD_PRIORITY_HIGHEST 20
00079 
00080 #elif defined(WIN32) || defined(UNDER_CE)
00081 /* Define different priorities for WinNT/2K/XP and Win9x/Me */
00082 #   define VLC_THREAD_PRIORITY_LOW 0
00083 #   define VLC_THREAD_PRIORITY_INPUT \
00084         THREAD_PRIORITY_ABOVE_NORMAL
00085 #   define VLC_THREAD_PRIORITY_AUDIO \
00086         THREAD_PRIORITY_HIGHEST
00087 #   define VLC_THREAD_PRIORITY_VIDEO 0
00088 #   define VLC_THREAD_PRIORITY_OUTPUT \
00089         THREAD_PRIORITY_ABOVE_NORMAL
00090 #   define VLC_THREAD_PRIORITY_HIGHEST \
00091         THREAD_PRIORITY_TIME_CRITICAL
00092 
00093 #else
00094 #   define VLC_THREAD_PRIORITY_LOW 0
00095 #   define VLC_THREAD_PRIORITY_INPUT 0
00096 #   define VLC_THREAD_PRIORITY_AUDIO 0
00097 #   define VLC_THREAD_PRIORITY_VIDEO 0
00098 #   define VLC_THREAD_PRIORITY_OUTPUT 0
00099 #   define VLC_THREAD_PRIORITY_HIGHEST 0
00100 
00101 #endif
00102 
00103 /*****************************************************************************
00104  * Type definitions
00105  *****************************************************************************/
00106 
00107 #if defined (LIBVLC_USE_PTHREAD)
00108 typedef pthread_t       vlc_thread_t;
00109 typedef pthread_mutex_t vlc_mutex_t;
00110 #define VLC_STATIC_MUTEX PTHREAD_MUTEX_INITIALIZER
00111 typedef pthread_cond_t  vlc_cond_t;
00112 #define VLC_STATIC_COND  PTHREAD_COND_INITIALIZER
00113 typedef pthread_rwlock_t vlc_rwlock_t;
00114 typedef pthread_key_t   vlc_threadvar_t;
00115 typedef struct vlc_timer *vlc_timer_t;
00116 
00117 #if defined (__APPLE__)
00118 typedef semaphore_t     vlc_sem_t;
00119 #else
00120 typedef sem_t           vlc_sem_t;
00121 #endif
00122 
00123 #elif defined( WIN32 )
00124 #if !defined( UNDER_CE )
00125 typedef HANDLE vlc_thread_t;
00126 #else
00127 typedef struct
00128 {
00129     HANDLE handle;
00130     HANDLE cancel_event;
00131 } *vlc_thread_t;
00132 #endif
00133 
00134 typedef struct
00135 {
00136     bool dynamic;
00137     union
00138     {
00139         struct
00140         {
00141             bool locked;
00142             unsigned long contention;
00143         };
00144         CRITICAL_SECTION mutex;
00145     };
00146 } vlc_mutex_t;
00147 #define VLC_STATIC_MUTEX { false, { { false, 0 } } }
00148 
00149 typedef struct
00150 {
00151     HANDLE   handle;
00152     unsigned clock;
00153 } vlc_cond_t;
00154 
00155 typedef HANDLE  vlc_sem_t;
00156 
00157 typedef struct
00158 {
00159     vlc_mutex_t   mutex;
00160     vlc_cond_t    read_wait;
00161     vlc_cond_t    write_wait;
00162     unsigned long readers;
00163     unsigned long writers;
00164     DWORD         writer;
00165 } vlc_rwlock_t;
00166 
00167 typedef DWORD   vlc_threadvar_t;
00168 typedef struct vlc_timer *vlc_timer_t;
00169 #endif
00170 
00171 #if defined( WIN32 ) && !defined ETIMEDOUT
00172 #  define ETIMEDOUT 10060 /* This is the value in winsock.h. */
00173 #endif
00174 
00175 /*****************************************************************************
00176  * Function definitions
00177  *****************************************************************************/
00178 VLC_EXPORT( void, vlc_mutex_init,    ( vlc_mutex_t * ) );
00179 VLC_EXPORT( void, vlc_mutex_init_recursive, ( vlc_mutex_t * ) );
00180 VLC_EXPORT( void, vlc_mutex_destroy, ( vlc_mutex_t * ) );
00181 VLC_EXPORT( void, vlc_mutex_lock, ( vlc_mutex_t * ) );
00182 VLC_EXPORT( int,  vlc_mutex_trylock, ( vlc_mutex_t * ) LIBVLC_USED );
00183 VLC_EXPORT( void, vlc_mutex_unlock, ( vlc_mutex_t * ) );
00184 VLC_EXPORT( void, vlc_cond_init,     ( vlc_cond_t * ) );
00185 VLC_EXPORT( void, vlc_cond_init_daytime, ( vlc_cond_t * ) );
00186 VLC_EXPORT( void, vlc_cond_destroy,  ( vlc_cond_t * ) );
00187 VLC_EXPORT( void, vlc_cond_signal, (vlc_cond_t *) );
00188 VLC_EXPORT( void, vlc_cond_broadcast, (vlc_cond_t *) );
00189 VLC_EXPORT( void, vlc_cond_wait, (vlc_cond_t *, vlc_mutex_t *) );
00190 VLC_EXPORT( int,  vlc_cond_timedwait, (vlc_cond_t *, vlc_mutex_t *, mtime_t) );
00191 VLC_EXPORT( void, vlc_sem_init, (vlc_sem_t *, unsigned) );
00192 VLC_EXPORT( void, vlc_sem_destroy, (vlc_sem_t *) );
00193 VLC_EXPORT( int,  vlc_sem_post, (vlc_sem_t *) );
00194 VLC_EXPORT( void, vlc_sem_wait, (vlc_sem_t *) );
00195 
00196 VLC_EXPORT( void, vlc_rwlock_init, (vlc_rwlock_t *) );
00197 VLC_EXPORT( void, vlc_rwlock_destroy, (vlc_rwlock_t *) );
00198 VLC_EXPORT( void, vlc_rwlock_rdlock, (vlc_rwlock_t *) );
00199 VLC_EXPORT( void, vlc_rwlock_wrlock, (vlc_rwlock_t *) );
00200 VLC_EXPORT( void, vlc_rwlock_unlock, (vlc_rwlock_t *) );
00201 VLC_EXPORT( int, vlc_threadvar_create, (vlc_threadvar_t * , void (*) (void *) ) );
00202 VLC_EXPORT( void, vlc_threadvar_delete, (vlc_threadvar_t *) );
00203 VLC_EXPORT( int, vlc_threadvar_set, (vlc_threadvar_t, void *) );
00204 VLC_EXPORT( void *, vlc_threadvar_get, (vlc_threadvar_t) );
00205 VLC_EXPORT( int,  vlc_thread_create, ( vlc_object_t *, const char *, int, const char *, void * ( * ) ( vlc_object_t * ), int ) LIBVLC_USED );
00206 VLC_EXPORT( int,  vlc_thread_set_priority, ( vlc_object_t *, const char *, int, int ) );
00207 VLC_EXPORT( void, vlc_thread_join,   ( vlc_object_t * ) );
00208 
00209 VLC_EXPORT( int, vlc_clone, (vlc_thread_t *, void * (*) (void *), void *, int) LIBVLC_USED );
00210 VLC_EXPORT( void, vlc_cancel, (vlc_thread_t) );
00211 VLC_EXPORT( void, vlc_join, (vlc_thread_t, void **) );
00212 VLC_EXPORT (void, vlc_control_cancel, (int cmd, ...));
00213 
00214 VLC_EXPORT( int, vlc_timer_create, (vlc_timer_t *, void (*) (void *), void *) LIBVLC_USED );
00215 VLC_EXPORT( void, vlc_timer_destroy, (vlc_timer_t) );
00216 VLC_EXPORT( void, vlc_timer_schedule, (vlc_timer_t, bool, mtime_t, mtime_t) );
00217 VLC_EXPORT( unsigned, vlc_timer_getoverrun, (vlc_timer_t) LIBVLC_USED );
00218 
00219 #ifndef LIBVLC_USE_PTHREAD_CANCEL
00220 enum {
00221     VLC_CLEANUP_PUSH,
00222     VLC_CLEANUP_POP,
00223 };
00224 #endif
00225 
00226 VLC_EXPORT( int, vlc_savecancel, (void) );
00227 VLC_EXPORT( void, vlc_restorecancel, (int state) );
00228 VLC_EXPORT( void, vlc_testcancel, (void) );
00229 
00230 #if defined (LIBVLC_USE_PTHREAD_CANCEL)
00231 /**
00232  * Registers a new procedure to run if the thread is cancelled (or otherwise
00233  * exits prematurely). Any call to vlc_cleanup_push() <b>must</b> paired with a
00234  * call to either vlc_cleanup_pop() or vlc_cleanup_run(). Branching into or out
00235  * of the block between these two function calls is not allowed (read: it will
00236  * likely crash the whole process). If multiple procedures are registered,
00237  * they are handled in last-in first-out order.
00238  *
00239  * @param routine procedure to call if the thread ends
00240  * @param arg argument for the procedure
00241  */
00242 # define vlc_cleanup_push( routine, arg ) pthread_cleanup_push (routine, arg)
00243 
00244 /**
00245  * Removes a cleanup procedure that was previously registered with
00246  * vlc_cleanup_push().
00247  */
00248 # define vlc_cleanup_pop( ) pthread_cleanup_pop (0)
00249 
00250 /**
00251  * Removes a cleanup procedure that was previously registered with
00252  * vlc_cleanup_push(), and executes it.
00253  */
00254 # define vlc_cleanup_run( ) pthread_cleanup_pop (1)
00255 #else
00256 typedef struct vlc_cleanup_t vlc_cleanup_t;
00257 
00258 struct vlc_cleanup_t
00259 {
00260     vlc_cleanup_t *next;
00261     void         (*proc) (void *);
00262     void          *data;
00263 };
00264 
00265 /* This macros opens a code block on purpose. This is needed for multiple
00266  * calls within a single function. This also prevent Win32 developers from
00267  * writing code that would break on POSIX (POSIX opens a block as well). */
00268 # define vlc_cleanup_push( routine, arg ) \
00269     do { \
00270         vlc_cleanup_t vlc_cleanup_data = { NULL, routine, arg, }; \
00271         vlc_control_cancel (VLC_CLEANUP_PUSH, &vlc_cleanup_data)
00272 
00273 # define vlc_cleanup_pop( ) \
00274         vlc_control_cancel (VLC_CLEANUP_POP); \
00275     } while (0)
00276 
00277 # define vlc_cleanup_run( ) \
00278         vlc_control_cancel (VLC_CLEANUP_POP); \
00279         vlc_cleanup_data.proc (vlc_cleanup_data.data); \
00280     } while (0)
00281 
00282 #endif /* LIBVLC_USE_PTHREAD_CANCEL */
00283 
00284 static inline void vlc_cleanup_lock (void *lock)
00285 {
00286     vlc_mutex_unlock ((vlc_mutex_t *)lock);
00287 }
00288 #define mutex_cleanup_push( lock ) vlc_cleanup_push (vlc_cleanup_lock, lock)
00289 
00290 # if defined (_POSIX_SPIN_LOCKS) && ((_POSIX_SPIN_LOCKS - 0) > 0)
00291 typedef pthread_spinlock_t vlc_spinlock_t;
00292 
00293 /**
00294  * Initializes a spinlock.
00295  */
00296 static inline void vlc_spin_init (vlc_spinlock_t *spin)
00297 {
00298     if (pthread_spin_init (spin, PTHREAD_PROCESS_PRIVATE))
00299         abort ();
00300 }
00301 
00302 /**
00303  * Acquires a spinlock.
00304  */
00305 static inline void vlc_spin_lock (vlc_spinlock_t *spin)
00306 {
00307     pthread_spin_lock (spin);
00308 }
00309 
00310 /**
00311  * Releases a spinlock.
00312  */
00313 static inline void vlc_spin_unlock (vlc_spinlock_t *spin)
00314 {
00315     pthread_spin_unlock (spin);
00316 }
00317 
00318 /**
00319  * Deinitializes a spinlock.
00320  */
00321 static inline void vlc_spin_destroy (vlc_spinlock_t *spin)
00322 {
00323     pthread_spin_destroy (spin);
00324 }
00325 
00326 #elif defined (WIN32) && !defined (UNDER_CE)
00327 
00328 typedef CRITICAL_SECTION vlc_spinlock_t;
00329 
00330 /**
00331  * Initializes a spinlock.
00332  */
00333 static inline void vlc_spin_init (vlc_spinlock_t *spin)
00334 {
00335     if (!InitializeCriticalSectionAndSpinCount(spin, 4000))
00336         abort ();
00337 }
00338 
00339 /**
00340  * Acquires a spinlock.
00341  */
00342 static inline void vlc_spin_lock (vlc_spinlock_t *spin)
00343 {
00344     EnterCriticalSection(spin);
00345 }
00346 
00347 /**
00348  * Releases a spinlock.
00349  */
00350 static inline void vlc_spin_unlock (vlc_spinlock_t *spin)
00351 {
00352     LeaveCriticalSection(spin);
00353 }
00354 
00355 /**
00356  * Deinitializes a spinlock.
00357  */
00358 static inline void vlc_spin_destroy (vlc_spinlock_t *spin)
00359 {
00360     DeleteCriticalSection(spin);
00361 }
00362 
00363 #else
00364 
00365 /* Fallback to plain mutexes if spinlocks are not available */
00366 typedef vlc_mutex_t vlc_spinlock_t;
00367 
00368 static inline void vlc_spin_init (vlc_spinlock_t *spin)
00369 {
00370     vlc_mutex_init (spin);
00371 }
00372 
00373 # define vlc_spin_lock    vlc_mutex_lock
00374 # define vlc_spin_unlock  vlc_mutex_unlock
00375 # define vlc_spin_destroy vlc_mutex_destroy
00376 #endif
00377 
00378 /**
00379  * Issues a full memory barrier.
00380  */
00381 #if defined (__APPLE__)
00382 # include <libkern/OSAtomic.h> /* OSMemoryBarrier() */
00383 #endif
00384 static inline void barrier (void)
00385 {
00386 #if defined (__GNUC__) && !defined (__APPLE__) && \
00387             ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
00388     __sync_synchronize ();
00389 #elif defined(__APPLE__)
00390     OSMemoryBarrier ();
00391 #elif defined(__powerpc__)
00392     asm volatile ("sync":::"memory");
00393 #elif 0 // defined(__i386__) /*  Requires SSE2 support */
00394     asm volatile ("mfence":::"memory");
00395 #else
00396     vlc_spinlock_t spin;
00397     vlc_spin_init (&spin);
00398     vlc_spin_lock (&spin);
00399     vlc_spin_unlock (&spin);
00400     vlc_spin_destroy (&spin);
00401 #endif
00402 }
00403 
00404 /*****************************************************************************
00405  * vlc_thread_create: create a thread
00406  *****************************************************************************/
00407 #define vlc_thread_create( P_THIS, PSZ_NAME, FUNC, PRIORITY )         \
00408     vlc_thread_create( VLC_OBJECT(P_THIS), __FILE__, __LINE__, PSZ_NAME, FUNC, PRIORITY )
00409 
00410 /*****************************************************************************
00411  * vlc_thread_set_priority: set the priority of the calling thread
00412  *****************************************************************************/
00413 #define vlc_thread_set_priority( P_THIS, PRIORITY )                         \
00414     vlc_thread_set_priority( VLC_OBJECT(P_THIS), __FILE__, __LINE__, PRIORITY )
00415 
00416 /*****************************************************************************
00417  * vlc_thread_join: wait until a thread exits
00418  *****************************************************************************/
00419 #define vlc_thread_join( P_THIS )                                           \
00420     vlc_thread_join( VLC_OBJECT(P_THIS) )
00421 
00422 #ifdef __cplusplus
00423 /**
00424  * Helper C++ class to lock a mutex.
00425  * The mutex is locked when the object is created, and unlocked when the object
00426  * is destroyed.
00427  */
00428 class vlc_mutex_locker
00429 {
00430     private:
00431         vlc_mutex_t *lock;
00432     public:
00433         vlc_mutex_locker (vlc_mutex_t *m) : lock (m)
00434         {
00435             vlc_mutex_lock (lock);
00436         }
00437 
00438         ~vlc_mutex_locker (void)
00439         {
00440             vlc_mutex_unlock (lock);
00441         }
00442 };
00443 #endif
00444 
00445 enum {
00446    VLC_AVCODEC_MUTEX = 0,
00447    VLC_GCRYPT_MUTEX,
00448    VLC_XLIB_MUTEX,
00449    /* Insert new entry HERE */
00450    VLC_MAX_MUTEX
00451 };
00452 
00453 VLC_EXPORT( void, vlc_global_mutex, ( unsigned, bool ) );
00454 #define vlc_global_lock( n ) vlc_global_mutex( n, true )
00455 #define vlc_global_unlock( n ) vlc_global_mutex( n, false )
00456 
00457 #endif /* !_VLC_THREADS_H */

Generated on Mon Nov 22 07:55:20 2010 for VLC by  doxygen 1.5.6