static dbus_bool_t
_dbus_condvar_wait_win32 (DBusCondVar *cond,
			  DBusMutex *mutex,
			  int milliseconds)
{
  DWORD retval;
  dbus_bool_t ret;
  HANDLE event = TlsGetValue (dbus_cond_event_tls);

  if (!event)
    {
      event = CreateEvent (0, FALSE, FALSE, NULL);
      if (event == 0)
	return FALSE;
      TlsSetValue (dbus_cond_event_tls, event);
    }

  EnterCriticalSection (&cond->lock);

  /* The event must not be signaled. Check this */
  _dbus_assert (WaitForSingleObject (event, 0) == WAIT_TIMEOUT);

  ret = _dbus_list_append (&cond->list, event);
  
  LeaveCriticalSection (&cond->lock);
  
  if (!ret)
    return FALSE; /* Prepend failed */

  _dbus_mutex_unlock (mutex);
  retval = WaitForSingleObject (event, milliseconds);
  _dbus_mutex_lock (mutex);
  
  if (retval == WAIT_TIMEOUT)
    {
      EnterCriticalSection (&cond->lock);
      _dbus_list_remove (&cond->list, event);

      /* In the meantime we could have been signaled, so we must again
       * wait for the signal, this time with no timeout, to reset
       * it. retval is set again to honour the late arrival of the
       * signal */
      retval = WaitForSingleObject (event, 0);

      LeaveCriticalSection (&cond->lock);
    }

#ifndef DBUS_DISABLE_ASSERT
  EnterCriticalSection (&cond->lock);

  /* Now event must not be inside the array, check this */
  _dbus_assert (_dbus_list_remove (&cond->list, event) == FALSE);

  LeaveCriticalSection (&cond->lock);
#endif /* !G_DISABLE_ASSERT */

  return retval != WAIT_TIMEOUT;
}
void
_dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
                                dbus_int32_t          *slot_id_p)
{
    _dbus_mutex_lock (*(allocator->lock_loc));

    _dbus_assert (*slot_id_p < allocator->n_allocated_slots);
    _dbus_assert (allocator->allocated_slots[*slot_id_p].slot_id == *slot_id_p);
    _dbus_assert (allocator->allocated_slots[*slot_id_p].refcount > 0);

    allocator->allocated_slots[*slot_id_p].refcount -= 1;

    if (allocator->allocated_slots[*slot_id_p].refcount > 0)
    {
        _dbus_mutex_unlock (*(allocator->lock_loc));
        return;
    }

    /* refcount is 0, free the slot */
    _dbus_verbose ("Freeing slot %d on allocator %p total %d allocated %d used\n",
                   *slot_id_p, allocator, allocator->n_allocated_slots, allocator->n_used_slots);

    allocator->allocated_slots[*slot_id_p].slot_id = -1;
    *slot_id_p = -1;

    allocator->n_used_slots -= 1;

    if (allocator->n_used_slots == 0)
    {
        DBusMutex **mutex_loc = allocator->lock_loc;

        dbus_free (allocator->allocated_slots);
        allocator->allocated_slots = NULL;
        allocator->n_allocated_slots = 0;
        allocator->lock_loc = NULL;

        _dbus_mutex_unlock (*mutex_loc);
    }
    else
    {
        _dbus_mutex_unlock (*(allocator->lock_loc));
    }
}
dbus_bool_t
_dbus_data_slot_list_set  (DBusDataSlotAllocator *allocator,
                           DBusDataSlotList      *list,
                           int                    slot,
                           void                  *data,
                           DBusFreeFunction       free_data_func,
                           DBusFreeFunction      *old_free_func,
                           void                 **old_data)
{
#ifndef DBUS_DISABLE_ASSERT
    /* We need to take the allocator lock here, because the allocator could
     * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts
     * are disabled, since then the asserts are empty.
     */
    _dbus_mutex_lock (*(allocator->lock_loc));
    _dbus_assert (slot < allocator->n_allocated_slots);
    _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
    _dbus_mutex_unlock (*(allocator->lock_loc));
#endif

    if (slot >= list->n_slots)
    {
        DBusDataSlot *tmp;
        int i;

        tmp = dbus_realloc (list->slots,
                            sizeof (DBusDataSlot) * (slot + 1));
        if (tmp == NULL)
            return FALSE;

        list->slots = tmp;
        i = list->n_slots;
        list->n_slots = slot + 1;
        while (i < list->n_slots)
        {
            list->slots[i].data = NULL;
            list->slots[i].free_data_func = NULL;
            ++i;
        }
    }

    _dbus_assert (slot < list->n_slots);

    *old_data = list->slots[slot].data;
    *old_free_func = list->slots[slot].free_data_func;

    list->slots[slot].data = data;
    list->slots[slot].free_data_func = free_data_func;

    return TRUE;
}
void*
_dbus_data_slot_list_get  (DBusDataSlotAllocator *allocator,
                           DBusDataSlotList      *list,
                           int                    slot)
{
#ifndef DBUS_DISABLE_ASSERT
    /* We need to take the allocator lock here, because the allocator could
     * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts
     * are disabled, since then the asserts are empty.
     */
    _dbus_mutex_lock (*(allocator->lock_loc));
    _dbus_assert (slot >= 0);
    _dbus_assert (slot < allocator->n_allocated_slots);
    _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
    _dbus_mutex_unlock (*(allocator->lock_loc));
#endif

    if (slot >= list->n_slots)
        return NULL;
    else
        return list->slots[slot].data;
}
dbus_bool_t
_dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator,
                                 DBusMutex             **mutex_loc,
                                 dbus_int32_t          *slot_id_p)
{
    dbus_int32_t slot;

    _dbus_mutex_lock (*mutex_loc);

    if (allocator->n_allocated_slots == 0)
    {
        _dbus_assert (allocator->lock_loc == NULL);
        allocator->lock_loc = mutex_loc;
    }
    else if (allocator->lock_loc != mutex_loc)
    {
        _dbus_warn_check_failed ("D-Bus threads were initialized after first using the D-Bus library. If your application does not directly initialize threads or use D-Bus, keep in mind that some library or plugin may have used D-Bus or initialized threads behind your back. You can often fix this problem by calling dbus_init_threads() or dbus_g_threads_init() early in your main() method, before D-Bus is used.\n");
        _dbus_assert_not_reached ("exiting");
    }

    if (*slot_id_p >= 0)
    {
        slot = *slot_id_p;

        _dbus_assert (slot < allocator->n_allocated_slots);
        _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);

        allocator->allocated_slots[slot].refcount += 1;

        goto out;
    }

    _dbus_assert (*slot_id_p < 0);

    if (allocator->n_used_slots < allocator->n_allocated_slots)
    {
        slot = 0;
        while (slot < allocator->n_allocated_slots)
        {
            if (allocator->allocated_slots[slot].slot_id < 0)
            {
                allocator->allocated_slots[slot].slot_id = slot;
                allocator->allocated_slots[slot].refcount = 1;
                allocator->n_used_slots += 1;
                break;
            }
            ++slot;
        }

        _dbus_assert (slot < allocator->n_allocated_slots);
    }
    else
    {
        DBusAllocatedSlot *tmp;

        slot = -1;
        tmp = dbus_realloc (allocator->allocated_slots,
                            sizeof (DBusAllocatedSlot) * (allocator->n_allocated_slots + 1));
        if (tmp == NULL)
            goto out;

        allocator->allocated_slots = tmp;
        slot = allocator->n_allocated_slots;
        allocator->n_allocated_slots += 1;
        allocator->n_used_slots += 1;
        allocator->allocated_slots[slot].slot_id = slot;
        allocator->allocated_slots[slot].refcount = 1;
    }

    _dbus_assert (slot >= 0);
    _dbus_assert (slot < allocator->n_allocated_slots);
    _dbus_assert (*slot_id_p < 0);
    _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
    _dbus_assert (allocator->allocated_slots[slot].refcount == 1);

    *slot_id_p = slot;

    _dbus_verbose ("Allocated slot %d on allocator %p total %d slots allocated %d used\n",
                   slot, allocator, allocator->n_allocated_slots, allocator->n_used_slots);

out:
    _dbus_mutex_unlock (*(allocator->lock_loc));
    return slot >= 0;
}