PortAudio 2.0
|
00001 /* 00002 * $Id: pa_unix_util.h 1241 2007-07-23 20:08:31Z aknudsen $ 00003 * Portable Audio I/O Library 00004 * UNIX platform-specific support functions 00005 * 00006 * Based on the Open Source API proposed by Ross Bencina 00007 * Copyright (c) 1999-2000 Ross Bencina 00008 * 00009 * Permission is hereby granted, free of charge, to any person obtaining 00010 * a copy of this software and associated documentation files 00011 * (the "Software"), to deal in the Software without restriction, 00012 * including without limitation the rights to use, copy, modify, merge, 00013 * publish, distribute, sublicense, and/or sell copies of the Software, 00014 * and to permit persons to whom the Software is furnished to do so, 00015 * subject to the following conditions: 00016 * 00017 * The above copyright notice and this permission notice shall be 00018 * included in all copies or substantial portions of the Software. 00019 * 00020 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00021 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00022 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00023 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 00024 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 00025 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 00026 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00027 */ 00028 00029 /* 00030 * The text above constitutes the entire PortAudio license; however, 00031 * the PortAudio community also makes the following non-binding requests: 00032 * 00033 * Any person wishing to distribute modifications to the Software is 00034 * requested to send the modifications to the original developer so that 00035 * they can be incorporated into the canonical version. It is also 00036 * requested that these non-binding requests be included along with the 00037 * license above. 00038 */ 00039 00044 #ifndef PA_UNIX_UTIL_H 00045 #define PA_UNIX_UTIL_H 00046 00047 #include "pa_cpuload.h" 00048 #include <assert.h> 00049 #include <pthread.h> 00050 #include <signal.h> 00051 00052 #ifdef __cplusplus 00053 extern "C" 00054 { 00055 #endif /* __cplusplus */ 00056 00057 #define PA_MIN(x,y) ( (x) < (y) ? (x) : (y) ) 00058 #define PA_MAX(x,y) ( (x) > (y) ? (x) : (y) ) 00059 00060 /* Utilize GCC branch prediction for error tests */ 00061 #if defined __GNUC__ && __GNUC__ >= 3 00062 #define UNLIKELY(expr) __builtin_expect( (expr), 0 ) 00063 #else 00064 #define UNLIKELY(expr) (expr) 00065 #endif 00066 00067 #define STRINGIZE_HELPER(expr) #expr 00068 #define STRINGIZE(expr) STRINGIZE_HELPER(expr) 00069 00070 #define PA_UNLESS(expr, code) \ 00071 do { \ 00072 if( UNLIKELY( (expr) == 0 ) ) \ 00073 { \ 00074 PaUtil_DebugPrint(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \ 00075 result = (code); \ 00076 goto error; \ 00077 } \ 00078 } while (0); 00079 00080 static PaError paUtilErr_; /* Used with PA_ENSURE */ 00081 00082 /* Check PaError */ 00083 #define PA_ENSURE(expr) \ 00084 do { \ 00085 if( UNLIKELY( (paUtilErr_ = (expr)) < paNoError ) ) \ 00086 { \ 00087 PaUtil_DebugPrint(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \ 00088 result = paUtilErr_; \ 00089 goto error; \ 00090 } \ 00091 } while (0); 00092 00093 #define PA_ASSERT_CALL(expr, success) \ 00094 paUtilErr_ = (expr); \ 00095 assert( success == paUtilErr_ ); 00096 00097 #define PA_ENSURE_SYSTEM(expr, success) \ 00098 do { \ 00099 if( UNLIKELY( (paUtilErr_ = (expr)) != success ) ) \ 00100 { \ 00101 /* PaUtil_SetLastHostErrorInfo should only be used in the main thread */ \ 00102 if( pthread_equal(pthread_self(), paUnixMainThread) ) \ 00103 { \ 00104 PaUtil_SetLastHostErrorInfo( paALSA, paUtilErr_, strerror( paUtilErr_ ) ); \ 00105 } \ 00106 PaUtil_DebugPrint( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" ); \ 00107 result = paUnanticipatedHostError; \ 00108 goto error; \ 00109 } \ 00110 } while( 0 ); 00111 00112 typedef struct { 00113 pthread_t callbackThread; 00114 } PaUtilThreading; 00115 00116 PaError PaUtil_InitializeThreading( PaUtilThreading *threading ); 00117 void PaUtil_TerminateThreading( PaUtilThreading *threading ); 00118 PaError PaUtil_StartThreading( PaUtilThreading *threading, void *(*threadRoutine)(void *), void *data ); 00119 PaError PaUtil_CancelThreading( PaUtilThreading *threading, int wait, PaError *exitResult ); 00120 00121 /* State accessed by utility functions */ 00122 00123 /* 00124 void PaUnix_SetRealtimeScheduling( int rt ); 00125 00126 void PaUtil_InitializeThreading( PaUtilThreading *th, PaUtilCpuLoadMeasurer *clm ); 00127 00128 PaError PaUtil_CreateCallbackThread( PaUtilThreading *th, void *(*CallbackThreadFunc)( void * ), PaStream *s ); 00129 00130 PaError PaUtil_KillCallbackThread( PaUtilThreading *th, PaError *exitResult ); 00131 00132 void PaUtil_CallbackUpdate( PaUtilThreading *th ); 00133 */ 00134 00135 extern pthread_t paUnixMainThread; 00136 00137 typedef struct 00138 { 00139 pthread_mutex_t mtx; 00140 } PaUnixMutex; 00141 00142 PaError PaUnixMutex_Initialize( PaUnixMutex* self ); 00143 PaError PaUnixMutex_Terminate( PaUnixMutex* self ); 00144 PaError PaUnixMutex_Lock( PaUnixMutex* self ); 00145 PaError PaUnixMutex_Unlock( PaUnixMutex* self ); 00146 00147 typedef struct 00148 { 00149 pthread_t thread; 00150 int parentWaiting; 00151 int stopRequested; 00152 int locked; 00153 PaUnixMutex mtx; 00154 pthread_cond_t cond; 00155 volatile sig_atomic_t stopRequest; 00156 } PaUnixThread; 00157 00160 PaError PaUnixThreading_Initialize(); 00161 00171 #define PaUnixThreading_EXIT(result) \ 00172 do { \ 00173 PaError* pres = NULL; \ 00174 if( paNoError != (result) ) \ 00175 { \ 00176 pres = malloc( sizeof (PaError) ); \ 00177 *pres = (result); \ 00178 } \ 00179 pthread_exit( pres ); \ 00180 } while (0); 00181 00193 PaError PaUnixThread_New( PaUnixThread* self, void* (*threadFunc)( void* ), void* threadArg, PaTime waitForChild, 00194 int rtSched ); 00195 00201 PaError PaUnixThread_Terminate( PaUnixThread* self, int wait, PaError* exitResult ); 00202 00209 PaError PaUnixThread_PrepareNotify( PaUnixThread* self ); 00210 00215 PaError PaUnixThread_NotifyParent( PaUnixThread* self ); 00216 00219 int PaUnixThread_StopRequested( PaUnixThread* self ); 00220 00221 #ifdef __cplusplus 00222 } 00223 #endif /* __cplusplus */ 00224 #endif