double sampleRate;
int callbackMode;
- int callbackStop, callbackAbort;
+ volatile int callbackStop, callbackAbort;
PaOssStreamComponent *capture, *playback;
unsigned long pollTimeout;
while( pollPlayback || pollCapture )
{
+#ifdef PTHREAD_CANCELED
pthread_testcancel();
+#else
+ /* avoid indefinite waiting on thread not supporting cancelation */
+ if( stream->callbackStop || stream->callbackAbort )
+ {
+ PA_DEBUG(( "Cancelling PaOssStream_WaitForFrames\n" ));
+ (*frames) = 0;
+ return paNoError;
+ }
+#endif
/* select may modify the timeout parameter */
selectTimeval.tv_usec = timeout;
ENSURE_( -1, paUnanticipatedHostError );
}
*/
+#ifdef PTHREAD_CANCELED
pthread_testcancel();
-
+#else
+ /* avoid indefinite waiting on thread not supporting cancelation */
+ if( stream->callbackStop || stream->callbackAbort )
+ {
+ PA_DEBUG(( "Cancelling PaOssStream_WaitForFrames\n" ));
+ (*frames) = 0;
+ return paNoError;
+ }
+#endif
if( pollCapture )
{
if( FD_ISSET( captureFd, &readFds ) )
while( 1 )
{
+#ifdef PTHREAD_CANCELED
pthread_testcancel();
-
+#else
+ if( stream->callbackAbort ) /* avoid indefinite waiting on thread not supporting cancelation */
+ {
+ PA_DEBUG(( "Aborting callback thread\n" ));
+ break;
+ }
+#endif
if( stream->callbackStop && callbackResult == paContinue )
{
PA_DEBUG(( "Setting callbackResult to paComplete\n" ));
{
unsigned long frames = framesAvail;
+#ifdef PTHREAD_CANCELED
pthread_testcancel();
+#else
+ if( stream->callbackStop )
+ {
+ PA_DEBUG(( "Setting callbackResult to paComplete\n" ));
+ callbackResult = paComplete;
+ }
+ if( stream->callbackAbort ) /* avoid indefinite waiting on thread not supporting cancelation */
+ {
+ PA_DEBUG(( "Aborting callback thread\n" ));
+ break;
+ }
+#endif
PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
/* Read data */
if( exitResult )
*exitResult = paNoError;
+ /* If pthread_cancel is not supported (Android platform) whole this function can lead to indefinite waiting if
+ working thread (callbackThread) has'n received any stop signals from outside, please keep
+ this in mind when considering using PaUtil_CancelThreading
+ */
+#ifdef PTHREAD_CANCELED
/* Only kill the thread if it isn't in the process of stopping (flushing adaptation buffers) */
if( !wait )
pthread_cancel( threading->callbackThread ); /* XXX: Safe to call this if the thread has exited on its own? */
+#endif
pthread_join( threading->callbackThread, &pret );
#ifdef PTHREAD_CANCELED
{
PA_DEBUG(( "%s: Canceling thread %d\n", __FUNCTION__, self->thread ));
/* XXX: Safe to call this if the thread has exited on its own? */
+#ifdef PTHREAD_CANCELED
pthread_cancel( self->thread );
+#endif
}
PA_DEBUG(( "%s: Joining thread %d\n", __FUNCTION__, self->thread ));
PA_ENSURE_SYSTEM( pthread_join( self->thread, &pret ), 0 );
+#ifdef PTHREAD_CANCELED
if( pret && PTHREAD_CANCELED != pret )
+#else
+ /* !wait means the thread may have been canceled */
+ if( pret && wait )
+#endif
{
if( exitResult )
{
PaError result = paNoError;
int oldState;
+#ifdef PTHREAD_CANCEL
PA_ENSURE_SYSTEM( pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldState ), 0 );
+#endif
PA_ENSURE_SYSTEM( pthread_mutex_lock( &self->mtx ), 0 );
error:
int oldState;
PA_ENSURE_SYSTEM( pthread_mutex_unlock( &self->mtx ), 0 );
+#ifdef PTHREAD_CANCEL
PA_ENSURE_SYSTEM( pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, &oldState ), 0 );
+#endif
error:
return result;