// must be volatile to avoid race condition on user query while
// thread is being started
- volatile BOOL running;
+ volatile LONG running;
PA_THREAD_ID dwThreadId;
HANDLE hThread;
typedef struct PaActivateAudioInterfaceCompletionHandler
{
IActivateAudioInterfaceCompletionHandler parent;
- ULONG refs;
- volatile BOOL done;
+ volatile LONG refs;
+ volatile LONG done;
struct
{
HRESULT hr;
// From MSDN:
// "The IAgileObject interface is a marker interface that indicates that an object
// is free threaded and can be called from any apartment."
- if (IsEqualIID(riid, &IID_IAgileObject))
+ if (IsEqualIID(riid, &IID_IUnknown) ||
+ IsEqualIID(riid, &IID_IAgileObject))
{
handler->parent.lpVtbl->AddRef((IActivateAudioInterfaceCompletionHandler *)handler);
(*ppvObject) = handler;
IActivateAudioInterfaceCompletionHandler *This)
{
PaActivateAudioInterfaceCompletionHandler *handler = (PaActivateAudioInterfaceCompletionHandler *)This;
- return ++ handler->refs;
+
+ return InterlockedIncrement(&handler->refs);
}
static ULONG (STDMETHODCALLTYPE PaActivateAudioInterfaceCompletionHandler_Release)(
IActivateAudioInterfaceCompletionHandler *This)
{
PaActivateAudioInterfaceCompletionHandler *handler = (PaActivateAudioInterfaceCompletionHandler *)This;
- if (handler->refs == 0)
+ ULONG refs;
+
+ if ((refs = InterlockedDecrement(&handler->refs)) == 0)
{
PaUtil_FreeMemory(handler->parent.lpVtbl);
PaUtil_FreeMemory(handler);
- return 0;
}
- return -- handler->refs;
+
+ return refs;
}
static HRESULT (STDMETHODCALLTYPE PaActivateAudioInterfaceCompletionHandler_ActivateCompleted)(
else
handler->out.hr = hr;
- handler->done = TRUE;
+ // Got client object, stop busy waiting in ActivateAudioInterface_WINRT
+ InterlockedExchange(&handler->done, TRUE);
+
return hr;
}
handler->parent.lpVtbl->AddRef = &PaActivateAudioInterfaceCompletionHandler_AddRef;
handler->parent.lpVtbl->Release = &PaActivateAudioInterfaceCompletionHandler_Release;
handler->parent.lpVtbl->ActivateCompleted = &PaActivateAudioInterfaceCompletionHandler_ActivateCompleted;
+ handler->refs = 1;
return (IActivateAudioInterfaceCompletionHandler *)handler;
}
#endif
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
// Wait in busy loop for async operation to complete
- while (SUCCEEDED(hr) && !handlerImpl->done)
+ while (SUCCEEDED(hr) && !InterlockedCompareExchange(&handlerImpl->done, FALSE, FALSE))
{
Sleep(1);
}
stream->out.clientProc = stream->out.clientParent;
// Signal: stream running.
- stream->running = TRUE;
+ InterlockedExchange(&stream->running, TRUE);
}
return result;
// Cleanup handles
_StreamCleanup(stream);
- stream->running = FALSE;
+ // Notify: not running
+ InterlockedExchange(&stream->running, FALSE);
}
// ------------------------------------------------------------------------------------------
SAFE_CLOSE(stream->hBlockingOpStreamWR);
}
+// ------------------------------------------------------------------------------------------
+static BOOL _IsStreamRunning(PaWasapiStream *stream)
+{
+ LONG retv;
+ do
+ {
+ retv = stream->running;
+ }
+ while (InterlockedCompareExchange(&stream->running, FALSE, FALSE) != retv);
+ return retv;
+}
+
// ------------------------------------------------------------------------------------------
static PaError StopStream( PaStream *s )
{
// ------------------------------------------------------------------------------------------
static PaError IsStreamStopped( PaStream *s )
{
- return !((PaWasapiStream *)s)->running;
+ return !_IsStreamRunning((PaWasapiStream *)s);
}
// ------------------------------------------------------------------------------------------
static PaError IsStreamActive( PaStream *s )
{
- return ((PaWasapiStream *)s)->running;
+ return _IsStreamRunning((PaWasapiStream *)s);
}
// ------------------------------------------------------------------------------------------
ThreadIdleScheduler sched;
// validate
- if (!stream->running)
+ if (!_IsStreamRunning(stream))
return paStreamIsStopped;
if (stream->captureClient == NULL)
return paBadStreamPtr;
ThreadIdleScheduler sched;
// validate
- if (!stream->running)
+ if (!_IsStreamRunning(stream))
return paStreamIsStopped;
if (stream->renderClient == NULL)
return paBadStreamPtr;
UINT32 available = 0;
// validate
- if (!stream->running)
+ if (!_IsStreamRunning(stream))
return paStreamIsStopped;
if (stream->captureClient == NULL)
return paBadStreamPtr;
UINT32 available = 0;
// validate
- if (!stream->running)
+ if (!_IsStreamRunning(stream))
return paStreamIsStopped;
if (stream->renderClient == NULL)
return paBadStreamPtr;
}
// Signal: stream running
- stream->running = TRUE;
+ InterlockedExchange(&stream->running, TRUE);
// Notify: thread started
SetEvent(stream->hThreadStart);
CoUninitialize();
// Notify: not running
- stream->running = FALSE;
+ InterlockedExchange(&stream->running, FALSE);
// Notify: thread exited
SetEvent(stream->hThreadExit);
}
// Signal: stream running
- stream->running = TRUE;
+ InterlockedExchange(&stream->running, TRUE);
// Notify: thread started
SetEvent(stream->hThreadStart);
CoUninitialize();
// Notify: not running
- stream->running = FALSE;
+ InterlockedExchange(&stream->running, FALSE);
// Notify: thread exited
SetEvent(stream->hThreadExit);