Bug 1133386 - Introduce an XASSERT() macro to libcubeb rather than (ab)using assert(). r=padenot f=dmajor
authorMatthew Gregan <kinetik@flim.org>
Fri, 20 Feb 2015 13:42:14 +1300
changeset 257057 1c7760c72b583da925ffe351fc4fec9e32717a77
parent 257056 d64f901863d6908e409913a7ce1ae231c34769c7
child 257058 a288fd1c1d0d9235ee36130929065ed90a0a98e2
push id4610
push userjlund@mozilla.com
push dateMon, 30 Mar 2015 18:32:55 +0000
treeherdermozilla-beta@4df54044d9ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1133386
milestone38.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1133386 - Introduce an XASSERT() macro to libcubeb rather than (ab)using assert(). r=padenot f=dmajor
media/libcubeb/README_MOZILLA
media/libcubeb/src/cubeb-internal.h
media/libcubeb/src/cubeb_wasapi.cpp
media/libcubeb/src/cubeb_winmm.c
--- a/media/libcubeb/README_MOZILLA
+++ b/media/libcubeb/README_MOZILLA
@@ -1,8 +1,8 @@
 The source from this directory was copied from the cubeb 
 git repository using the update.sh script.  The only changes
 made were those applied by update.sh and the addition of
 Makefile.in build files for the Mozilla build system.
 
 The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
 
-The git commit ID used was 699aadf4d5e4c14a7e87b4f4add9cbc938feecc2.
+The git commit ID used was cacaae79dd8b7220202d0dfe3f889d55e23a77a5.
--- a/media/libcubeb/src/cubeb-internal.h
+++ b/media/libcubeb/src/cubeb-internal.h
@@ -34,10 +34,17 @@ struct cubeb_ops {
                                     cubeb_device ** const device);
   int (* stream_device_destroy)(cubeb_stream * stream,
                                 cubeb_device * device);
   int (* stream_register_device_changed_callback)(cubeb_stream * stream,
                                                   cubeb_device_changed_callback device_changed_callback);
 
 };
 
+#define XASSERT(expr) do {                                              \
+    if (!(expr)) {                                                      \
+      fprintf(stderr, "%s:%d - fatal error: %s\n", __FILE__, __LINE__, #expr); \
+      *((volatile int *) NULL) = 0;                                     \
+      abort();                                                          \
+    }                                                                   \
+  } while (0)
+
 #endif /* CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5 */
-
--- a/media/libcubeb/src/cubeb_wasapi.cpp
+++ b/media/libcubeb/src/cubeb_wasapi.cpp
@@ -1,35 +1,30 @@
 /*
  * Copyright  2013 Mozilla Foundation
  *
  * This program is made available under an ISC-style license.  See the
  * accompanying file LICENSE for details.
  */
 // This enables assert in release, and lets us have debug-only code
-#ifdef NDEBUG
-#define DEBUG
-#undef NDEBUG
-#endif // #ifdef NDEBUG
-
 #if defined(HAVE_CONFIG_H)
 #include "config.h"
 #endif
-#include <assert.h>
 #include <windows.h>
 #include <mmdeviceapi.h>
 #include <windef.h>
 #include <audioclient.h>
 #include <process.h>
 #include <avrt.h>
 #include "cubeb/cubeb.h"
 #include "cubeb-internal.h"
 #include "cubeb/cubeb-stdint.h"
 #include "cubeb_resampler.h"
 #include <stdio.h>
+#include <stdlib.h>
 #include <cmath>
 
 /**Taken from winbase.h, Not in MinGW.*/
 #ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
 #define STACK_SIZE_PARAM_IS_A_RESERVATION   0x00010000    // Threads only
 #endif
 
 // #define LOGGING_ENABLED
@@ -97,17 +92,17 @@ public:
   {
     DeleteCriticalSection(&critical_section);
   }
 
   void enter()
   {
     EnterCriticalSection(&critical_section);
 #ifdef DEBUG
-    assert(owner != GetCurrentThreadId() && "recursive locking");
+    XASSERT(owner != GetCurrentThreadId() && "recursive locking");
     owner = GetCurrentThreadId();
 #endif
   }
 
   void leave()
   {
 #ifdef DEBUG
     /* GetCurrentThreadId cannot return 0: it is not a the valid thread id */
@@ -117,17 +112,17 @@ public:
   }
 
   /* This is guaranteed to have the good behaviour if it succeeds. The behaviour
    * is undefined otherwise. */
   void assert_current_thread_owns()
   {
 #ifdef DEBUG
     /* This implies owner != 0, because GetCurrentThreadId cannot return 0. */
-    assert(owner == GetCurrentThreadId());
+    XASSERT(owner == GetCurrentThreadId());
 #endif
   }
 
 private:
   CRITICAL_SECTION critical_section;
 #ifdef DEBUG
   DWORD owner;
 #endif
@@ -384,17 +379,17 @@ mono_to_stereo(T * in, long insamples, T
     out[j] = out[j + 1] = in[i];
   }
 }
 
 template<typename T>
 void
 upmix(T * in, long inframes, T * out, int32_t in_channels, int32_t out_channels)
 {
-  assert(out_channels >= in_channels);
+  XASSERT(out_channels >= in_channels);
   /* If we are playing a mono stream over stereo speakers, copy the data over. */
   if (in_channels == 1 && out_channels == 2) {
     mono_to_stereo(in, inframes, out);
     return;
   }
   /* Otherwise, put silence in other channels. */
   long out_index = 0;
   for (long i = 0; i < inframes * in_channels; i += in_channels) {
@@ -407,17 +402,17 @@ upmix(T * in, long inframes, T * out, in
     out_index += out_channels;
   }
 }
 
 template<typename T>
 void
 downmix(T * in, long inframes, T * out, int32_t in_channels, int32_t out_channels)
 {
-  assert(in_channels >= out_channels);
+  XASSERT(in_channels >= out_channels);
   /* We could use a downmix matrix here, applying mixing weight based on the
    * channel, but directsound and winmm simply drop the channels that cannot be
    * rendered by the hardware, so we do the same for consistency. */
   long out_index = 0;
   for (long i = 0; i < inframes * in_channels; i += in_channels) {
     for (int j = 0; j < out_channels; ++j) {
       out[out_index + j] = in[i + j];
     }
@@ -447,28 +442,28 @@ refill(cubeb_stream * stm, float * data,
   }
 
   long out_frames = cubeb_resampler_fill(stm->resampler, dest, frames_needed);
 
   clock_add(stm, roundf(frames_needed * stream_to_mix_samplerate_ratio(stm)));
 
   /* XXX: Handle this error. */
   if (out_frames < 0) {
-    assert(false);
+    XASSERT(false);
   }
 
   /* Go in draining mode if we got fewer frames than requested. */
   if (out_frames < frames_needed) {
     LOG("draining.\n");
     stm->draining = true;
   }
 
   /* If this is not true, there will be glitches.
    * It is alright to have produced less frames if we are draining, though. */
-  assert(out_frames == frames_needed || stm->draining);
+  XASSERT(out_frames == frames_needed || stm->draining);
 
   if (should_upmix(stm)) {
     upmix(dest, out_frames, data,
           stm->stream_params.channels, stm->mix_params.channels);
   } else if (should_downmix(stm)) {
     downmix(dest, out_frames, data,
             stm->stream_params.channels, stm->mix_params.channels);
   }
@@ -534,17 +529,17 @@ wasapi_stream_render_loop(LPVOID stream)
       UINT32 padding;
 
       hr = stm->client->GetCurrentPadding(&padding);
       if (FAILED(hr)) {
         LOG("Failed to get padding\n");
         is_playing = false;
         continue;
       }
-      assert(padding <= stm->buffer_frame_count);
+      XASSERT(padding <= stm->buffer_frame_count);
 
       if (stm->draining) {
         if (padding == 0) {
           stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
           is_playing = false;
         }
         continue;
       }
@@ -567,17 +562,17 @@ wasapi_stream_render_loop(LPVOID stream)
         }
       } else {
         LOG("failed to get buffer.\n");
         is_playing = false;
       }
     }
       break;
     case WAIT_TIMEOUT:
-      assert(stm->shutdown_event == wait_array[0]);
+      XASSERT(stm->shutdown_event == wait_array[0]);
       is_playing = false;
       hr = -1;
       break;
     default:
       LOG("case %d not handled in render loop.", waitResult);
       abort();
     }
   }
@@ -623,17 +618,17 @@ HRESULT register_notification_client(cub
     return hr;
   }
 
   return hr;
 }
 
 HRESULT unregister_notification_client(cubeb_stream * stm)
 {
-  assert(stm);
+  XASSERT(stm);
 
   if (!stm->device_enumerator) {
     return S_OK;
   }
 
   stm->device_enumerator->UnregisterEndpointNotificationCallback(stm->notification_client);
 
   SafeRelease(stm->notification_client);
@@ -763,17 +758,17 @@ wasapi_get_max_channel_count(cubeb * ctx
   HRESULT hr;
   IAudioClient * client;
   WAVEFORMATEX * mix_format;
   auto_com com;
   if (!com.ok()) {
     return CUBEB_ERROR;
   }
 
-  assert(ctx && max_channels);
+  XASSERT(ctx && max_channels);
 
   IMMDevice * device;
   hr = get_default_endpoint(&device);
   if (FAILED(hr)) {
     return CUBEB_ERROR;
   }
 
   hr = device->Activate(__uuidof(IAudioClient),
@@ -915,17 +910,17 @@ handle_channel_layout(cubeb_stream * stm
   switch (stream_params->channels) {
     case 1: /* Mono */
       format_pcm->dwChannelMask = KSAUDIO_SPEAKER_MONO;
       break;
     case 2: /* Stereo */
       format_pcm->dwChannelMask = KSAUDIO_SPEAKER_STEREO;
       break;
     default:
-      assert(false && "Channel layout not supported.");
+      XASSERT(false && "Channel layout not supported.");
       break;
   }
   (*mix_format)->nChannels = stream_params->channels;
   (*mix_format)->nBlockAlign = ((*mix_format)->wBitsPerSample * (*mix_format)->nChannels) / 8;
   (*mix_format)->nAvgBytesPerSec = (*mix_format)->nSamplesPerSec * (*mix_format)->nBlockAlign;
   format_pcm->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
   (*mix_format)->wBitsPerSample = 32;
   format_pcm->Samples.wValidBitsPerSample = (*mix_format)->wBitsPerSample;
@@ -936,17 +931,17 @@ handle_channel_layout(cubeb_stream * stm
                                               *mix_format,
                                               &closest);
 
   if (hr == S_FALSE) {
     /* Not supported, but WASAPI gives us a suggestion. Use it, and handle the
      * eventual upmix/downmix ourselves */
     LOG("Using WASAPI suggested format: channels: %d\n", closest->nChannels);
     WAVEFORMATEXTENSIBLE * closest_pcm = reinterpret_cast<WAVEFORMATEXTENSIBLE *>(closest);
-    assert(closest_pcm->SubFormat == format_pcm->SubFormat);
+    XASSERT(closest_pcm->SubFormat == format_pcm->SubFormat);
     CoTaskMemFree(*mix_format);
     *mix_format = closest;
   } else if (hr == AUDCLNT_E_UNSUPPORTED_FORMAT) {
     /* Not supported, no suggestion. This should not happen, but it does in the
      * field with some sound cards. We restore the mix format, and let the rest
      * of the code figure out the right conversion path. */
     **mix_format = hw_mixformat;
   } else if (hr == S_OK) {
@@ -962,17 +957,17 @@ int setup_wasapi_stream(cubeb_stream * s
 
   stm->stream_reset_lock->assert_current_thread_owns();
 
   auto_com com;
   if (!com.ok()) {
     return CUBEB_ERROR;
   }
 
-  assert(!stm->client && "WASAPI stream already setup, close it first.");
+  XASSERT(!stm->client && "WASAPI stream already setup, close it first.");
 
   hr = get_default_endpoint(&device);
   if (FAILED(hr)) {
     LOG("Could not get default endpoint, error: %x\n", hr);
     stm->stream_reset_lock->leave();
     wasapi_stream_destroy(stm);
     return CUBEB_ERROR;
   }
@@ -1091,21 +1086,21 @@ wasapi_stream_init(cubeb * context, cube
 {
   HRESULT hr;
   int rv;
   auto_com com;
   if (!com.ok()) {
     return CUBEB_ERROR;
   }
 
-  assert(context && stream);
+  XASSERT(context && stream);
 
   cubeb_stream * stm = (cubeb_stream *)calloc(1, sizeof(cubeb_stream));
 
-  assert(stm);
+  XASSERT(stm);
 
   stm->context = context;
   stm->data_callback = data_callback;
   stm->state_callback = state_callback;
   stm->user_ptr = user_ptr;
   stm->stream_params = stream_params;
   stm->draining = false;
   stm->latency = latency;
@@ -1155,17 +1150,17 @@ wasapi_stream_init(cubeb * context, cube
 
   *stream = stm;
 
   return CUBEB_OK;
 }
 
 void close_wasapi_stream(cubeb_stream * stm)
 {
-  assert(stm);
+  XASSERT(stm);
 
   stm->stream_reset_lock->assert_current_thread_owns();
 
   SafeRelease(stm->client);
   stm->client = NULL;
 
   SafeRelease(stm->render_client);
   stm->render_client = NULL;
@@ -1176,17 +1171,17 @@ void close_wasapi_stream(cubeb_stream * 
   }
 
   free(stm->mix_buffer);
   stm->mix_buffer = NULL;
 }
 
 void wasapi_stream_destroy(cubeb_stream * stm)
 {
-  assert(stm);
+  XASSERT(stm);
 
   unregister_notification_client(stm);
 
   stop_and_join_render_thread(stm);
 
   SafeRelease(stm->reconfigure_event);
   SafeRelease(stm->refill_event);
 
@@ -1199,17 +1194,17 @@ void wasapi_stream_destroy(cubeb_stream 
 
   free(stm);
 }
 
 int wasapi_stream_start(cubeb_stream * stm)
 {
   auto_lock lock(stm->stream_reset_lock);
 
-  assert(stm && !stm->thread && !stm->shutdown_event);
+  XASSERT(stm && !stm->thread && !stm->shutdown_event);
 
   stm->shutdown_event = CreateEvent(NULL, 0, 0, NULL);
   if (!stm->shutdown_event) {
     LOG("Can't create the shutdown event, error: %x\n", GetLastError());
     return CUBEB_ERROR;
   }
 
   stm->thread = (HANDLE) _beginthreadex(NULL, 256 * 1024, wasapi_stream_render_loop, stm, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL);
@@ -1226,17 +1221,17 @@ int wasapi_stream_start(cubeb_stream * s
     stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);
   }
 
   return FAILED(hr) ? CUBEB_ERROR : CUBEB_OK;
 }
 
 int wasapi_stream_stop(cubeb_stream * stm)
 {
-  assert(stm);
+  XASSERT(stm);
 
   auto_lock lock(stm->stream_reset_lock);
 
   HRESULT hr = stm->client->Stop();
   if (FAILED(hr)) {
     LOG("could not stop AudioClient\n");
   }
 
@@ -1248,26 +1243,26 @@ int wasapi_stream_stop(cubeb_stream * st
     stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
   }
 
   return FAILED(hr) ? CUBEB_ERROR : CUBEB_OK;
 }
 
 int wasapi_stream_get_position(cubeb_stream * stm, uint64_t * position)
 {
-  assert(stm && position);
+  XASSERT(stm && position);
 
   *position = clock_get(stm);
 
   return CUBEB_OK;
 }
 
 int wasapi_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
 {
-  assert(stm && latency);
+  XASSERT(stm && latency);
 
   auto_lock lock(stm->stream_reset_lock);
 
   /* The GetStreamLatency method only works if the
    * AudioClient has been initialized. */
   if (!stm->client) {
     return CUBEB_ERROR;
   }
@@ -1290,17 +1285,17 @@ int wasapi_stream_set_volume(cubeb_strea
   auto_lock lock(stm->stream_reset_lock);
 
   hr = stm->audio_stream_volume->GetChannelCount(&channels);
   if (hr != S_OK) {
     LOG("could not get the channel count: %x\n", hr);
     return CUBEB_ERROR;
   }
 
-  assert(channels <= 10 && "bump the array size");
+  XASSERT(channels <= 10 && "bump the array size");
 
   for (uint32_t i = 0; i < channels; i++) {
     volumes[i] = volume;
   }
 
   hr = stm->audio_stream_volume->SetAllVolumes(channels,  volumes);
   if (hr != S_OK) {
     LOG("could not set the channels volume: %x\n", hr);
--- a/media/libcubeb/src/cubeb_winmm.c
+++ b/media/libcubeb/src/cubeb_winmm.c
@@ -1,27 +1,26 @@
 /*
  * Copyright © 2011 Mozilla Foundation
  *
  * This program is made available under an ISC-style license.  See the
  * accompanying file LICENSE for details.
  */
-#undef NDEBUG
 #define __MSVCRT_VERSION__ 0x0700
 #undef WINVER
 #define WINVER 0x0501
 #undef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
 
 #include <malloc.h>
-#include <assert.h>
 #include <windows.h>
 #include <mmreg.h>
 #include <mmsystem.h>
 #include <process.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 #include "cubeb/cubeb.h"
 #include "cubeb-internal.h"
 
 /* This is missing from the MinGW headers. Use a safe fallback. */
 #if !defined(MEMORY_ALLOCATION_ALIGNMENT)
 #define MEMORY_ALLOCATION_ALIGNMENT 16
@@ -90,48 +89,48 @@ bytes_per_frame(cubeb_stream_params para
   switch (params.format) {
   case CUBEB_SAMPLE_S16LE:
     bytes = sizeof(signed short);
     break;
   case CUBEB_SAMPLE_FLOAT32LE:
     bytes = sizeof(float);
     break;
   default:
-    assert(0);
+    XASSERT(0);
   }
 
   return bytes * params.channels;
 }
 
 static WAVEHDR *
 winmm_get_next_buffer(cubeb_stream * stm)
 {
   WAVEHDR * hdr = NULL;
 
-  assert(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
+  XASSERT(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
   hdr = &stm->buffers[stm->next_buffer];
-  assert(hdr->dwFlags & WHDR_PREPARED ||
-         (hdr->dwFlags & WHDR_DONE && !(hdr->dwFlags & WHDR_INQUEUE)));
+  XASSERT(hdr->dwFlags & WHDR_PREPARED ||
+          (hdr->dwFlags & WHDR_DONE && !(hdr->dwFlags & WHDR_INQUEUE)));
   stm->next_buffer = (stm->next_buffer + 1) % NBUFS;
   stm->free_buffers -= 1;
 
   return hdr;
 }
 
 static void
 winmm_refill_stream(cubeb_stream * stm)
 {
   WAVEHDR * hdr;
   long got;
   long wanted;
   MMRESULT r;
 
   EnterCriticalSection(&stm->lock);
   stm->free_buffers += 1;
-  assert(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
+  XASSERT(stm->free_buffers > 0 && stm->free_buffers <= NBUFS);
 
   if (stm->draining) {
     LeaveCriticalSection(&stm->lock);
     if (stm->free_buffers == NBUFS) {
       stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
     }
     SetEvent(stm->event);
     return;
@@ -150,27 +149,27 @@ winmm_refill_stream(cubeb_stream * stm)
   /* It is assumed that the caller is holding this lock.  It must be dropped
      during the callback to avoid deadlocks. */
   LeaveCriticalSection(&stm->lock);
   got = stm->data_callback(stm, stm->user_ptr, hdr->lpData, wanted);
   EnterCriticalSection(&stm->lock);
   if (got < 0) {
     LeaveCriticalSection(&stm->lock);
     /* XXX handle this case */
-    assert(0);
+    XASSERT(0);
     return;
   } else if (got < wanted) {
     stm->draining = 1;
   }
   stm->written += got;
 
-  assert(hdr->dwFlags & WHDR_PREPARED);
+  XASSERT(hdr->dwFlags & WHDR_PREPARED);
 
   hdr->dwBufferLength = got * bytes_per_frame(stm->params);
-  assert(hdr->dwBufferLength <= stm->buffer_size);
+  XASSERT(hdr->dwBufferLength <= stm->buffer_size);
 
   if (stm->soft_volume != -1.0) {
     if (stm->params.format == CUBEB_SAMPLE_FLOAT32NE) {
       float * b = (float *) hdr->lpData;
       uint32_t i;
       for (i = 0; i < got * stm->params.channels; i++) {
         b[i] *= stm->soft_volume;
       }
@@ -192,24 +191,24 @@ winmm_refill_stream(cubeb_stream * stm)
 
   LeaveCriticalSection(&stm->lock);
 }
 
 static unsigned __stdcall
 winmm_buffer_thread(void * user_ptr)
 {
   cubeb * ctx = (cubeb *) user_ptr;
-  assert(ctx);
+  XASSERT(ctx);
 
   for (;;) {
     DWORD r;
     PSLIST_ENTRY item;
 
     r = WaitForSingleObject(ctx->event, INFINITE);
-    assert(r == WAIT_OBJECT_0);
+    XASSERT(r == WAIT_OBJECT_0);
 
     /* Process work items in batches so that a single stream can't
        starve the others by continuously adding new work to the top of
        the work item stack. */
     item = InterlockedFlushSList(ctx->work);
     while (item != NULL) {
       PSLIST_ENTRY tmp = item;
       winmm_refill_stream(((struct cubeb_stream_item *) tmp)->stream);
@@ -231,17 +230,17 @@ winmm_buffer_callback(HWAVEOUT waveout, 
   cubeb_stream * stm = (cubeb_stream *) user_ptr;
   struct cubeb_stream_item * item;
 
   if (msg != WOM_DONE) {
     return;
   }
 
   item = _aligned_malloc(sizeof(struct cubeb_stream_item), MEMORY_ALLOCATION_ALIGNMENT);
-  assert(item);
+  XASSERT(item);
   item->stream = stm;
   InterlockedPushEntrySList(stm->context->work, &item->head);
 
   SetEvent(stm->context->event);
 }
 
 static unsigned int
 calculate_minimum_latency(void)
@@ -273,26 +272,26 @@ calculate_minimum_latency(void)
 
 static void winmm_destroy(cubeb * ctx);
 
 /*static*/ int
 winmm_init(cubeb ** context, char const * context_name)
 {
   cubeb * ctx;
 
-  assert(context);
+  XASSERT(context);
   *context = NULL;
 
   ctx = calloc(1, sizeof(*ctx));
-  assert(ctx);
+  XASSERT(ctx);
 
   ctx->ops = &winmm_ops;
 
   ctx->work = _aligned_malloc(sizeof(*ctx->work), MEMORY_ALLOCATION_ALIGNMENT);
-  assert(ctx->work);
+  XASSERT(ctx->work);
   InitializeSListHead(ctx->work);
 
   ctx->event = CreateEvent(NULL, FALSE, FALSE, NULL);
   if (!ctx->event) {
     winmm_destroy(ctx);
     return CUBEB_ERROR;
   }
 
@@ -320,26 +319,26 @@ winmm_get_backend_id(cubeb * ctx)
   return "winmm";
 }
 
 static void
 winmm_destroy(cubeb * ctx)
 {
   DWORD r;
 
-  assert(ctx->active_streams == 0);
-  assert(!InterlockedPopEntrySList(ctx->work));
+  XASSERT(ctx->active_streams == 0);
+  XASSERT(!InterlockedPopEntrySList(ctx->work));
 
   DeleteCriticalSection(&ctx->lock);
 
   if (ctx->thread) {
     ctx->shutdown = 1;
     SetEvent(ctx->event);
     r = WaitForSingleObject(ctx->thread, INFINITE);
-    assert(r == WAIT_OBJECT_0);
+    XASSERT(r == WAIT_OBJECT_0);
     CloseHandle(ctx->thread);
   }
 
   if (ctx->event) {
     CloseHandle(ctx->event);
   }
 
   _aligned_free(ctx->work);
@@ -357,18 +356,18 @@ winmm_stream_init(cubeb * context, cubeb
                   void * user_ptr)
 {
   MMRESULT r;
   WAVEFORMATEXTENSIBLE wfx;
   cubeb_stream * stm;
   int i;
   size_t bufsz;
 
-  assert(context);
-  assert(stream);
+  XASSERT(context);
+  XASSERT(stream);
 
   *stream = NULL;
 
   memset(&wfx, 0, sizeof(wfx));
   if (stream_params.channels > 2) {
     wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
     wfx.Format.cbSize = sizeof(wfx) - sizeof(wfx.Format);
   } else {
@@ -408,17 +407,17 @@ winmm_stream_init(cubeb * context, cubeb
   if (context->active_streams >= CUBEB_STREAM_MAX) {
     LeaveCriticalSection(&context->lock);
     return CUBEB_ERROR;
   }
   context->active_streams += 1;
   LeaveCriticalSection(&context->lock);
 
   stm = calloc(1, sizeof(*stm));
-  assert(stm);
+  XASSERT(stm);
 
   stm->context = context;
 
   stm->params = stream_params;
 
   stm->data_callback = data_callback;
   stm->state_callback = state_callback;
   stm->user_ptr = user_ptr;
@@ -427,17 +426,17 @@ winmm_stream_init(cubeb * context, cubeb
   if (latency < context->minimum_latency) {
     latency = context->minimum_latency;
   }
 
   bufsz = (size_t) (stm->params.rate / 1000.0 * latency * bytes_per_frame(stm->params) / NBUFS);
   if (bufsz % bytes_per_frame(stm->params) != 0) {
     bufsz += bytes_per_frame(stm->params) - (bufsz % bytes_per_frame(stm->params));
   }
-  assert(bufsz % bytes_per_frame(stm->params) == 0);
+  XASSERT(bufsz % bytes_per_frame(stm->params) == 0);
 
   stm->buffer_size = bufsz;
 
   InitializeCriticalSection(&stm->lock);
 
   stm->event = CreateEvent(NULL, FALSE, FALSE, NULL);
   if (!stm->event) {
     winmm_stream_destroy(stm);
@@ -462,17 +461,17 @@ winmm_stream_init(cubeb * context, cubeb
     return CUBEB_ERROR;
   }
 
 
   for (i = 0; i < NBUFS; ++i) {
     WAVEHDR * hdr = &stm->buffers[i];
 
     hdr->lpData = calloc(1, bufsz);
-    assert(hdr->lpData);
+    XASSERT(hdr->lpData);
     hdr->dwBufferLength = bufsz;
     hdr->dwFlags = 0;
 
     r = waveOutPrepareHeader(stm->waveout, hdr, sizeof(*hdr));
     if (r != MMSYSERR_NOERROR) {
       winmm_stream_destroy(stm);
       return CUBEB_ERROR;
     }
@@ -499,17 +498,17 @@ winmm_stream_destroy(cubeb_stream * stm)
     waveOutReset(stm->waveout);
 
     enqueued = NBUFS - stm->free_buffers;
     LeaveCriticalSection(&stm->lock);
 
     /* Wait for all blocks to complete. */
     while (enqueued > 0) {
       r = WaitForSingleObject(stm->event, INFINITE);
-      assert(r == WAIT_OBJECT_0);
+      XASSERT(r == WAIT_OBJECT_0);
 
       EnterCriticalSection(&stm->lock);
       enqueued = NBUFS - stm->free_buffers;
       LeaveCriticalSection(&stm->lock);
     }
 
     EnterCriticalSection(&stm->lock);
 
@@ -530,27 +529,27 @@ winmm_stream_destroy(cubeb_stream * stm)
 
   DeleteCriticalSection(&stm->lock);
 
   for (i = 0; i < NBUFS; ++i) {
     free(stm->buffers[i].lpData);
   }
 
   EnterCriticalSection(&stm->context->lock);
-  assert(stm->context->active_streams >= 1);
+  XASSERT(stm->context->active_streams >= 1);
   stm->context->active_streams -= 1;
   LeaveCriticalSection(&stm->context->lock);
 
   free(stm);
 }
 
 static int
 winmm_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
 {
-  assert(ctx && max_channels);
+  XASSERT(ctx && max_channels);
 
   /* We don't support more than two channels in this backend. */
   *max_channels = 2;
 
   return CUBEB_OK;
 }
 
 static int