[pulseaudio-discuss] [PATCH] hashmap: Allow freeing of keys in addition to values

David Henningsson david.henningsson at canonical.com
Tue Aug 6 03:55:49 PDT 2013


On 08/06/2013 11:02 AM, Arun Raghavan wrote:
> This is handy for cases where we want to have the key freed at entry
> removal or hashmap free'ing time. For example, this is useful when
> creating a hashmap based on non-static strings.

I agree about the problem about string keys, but I think the
implementation could be more elegant:

1) The free_cb functions could be supplied with pa_hashmap_new and
stored inside the hashmap, rather than being supplied in several places.

2) This applies mostly to strings. Could we perhaps make a convenience
layer for string-key hashmaps, like this:

pa_hashmap_put_strkey(const char *strkey, void *value) {
  void *key = pa_strdup(strkey);
  pa_hashmap_put(key, value);
}

...and similar for other functions, when necessary?


> ---
>  src/modules/alsa/alsa-mixer.c                      | 28 ++++++-------
>  src/modules/alsa/module-alsa-card.c                |  2 +-
>  src/modules/bluetooth/bluetooth-util.c             | 14 +++----
>  src/modules/bluetooth/module-bluetooth-discover.c  |  6 +--
>  src/modules/bluetooth/module-bluetooth-proximity.c |  6 +--
>  src/modules/dbus/iface-card.c                      |  6 +--
>  src/modules/dbus/iface-core.c                      | 48 +++++++++++-----------
>  src/modules/dbus/iface-device.c                    |  6 +--
>  src/modules/gconf/module-gconf.c                   |  4 +-
>  src/modules/macosx/module-bonjour-publish.c        |  4 +-
>  src/modules/module-augment-properties.c            |  4 +-
>  src/modules/module-card-restore.c                  |  2 +-
>  src/modules/module-console-kit.c                   |  4 +-
>  src/modules/module-device-manager.c                | 16 ++++----
>  src/modules/module-filter-apply.c                  | 10 ++---
>  src/modules/module-role-cork.c                     |  6 +--
>  src/modules/module-stream-restore.c                |  8 ++--
>  src/modules/module-suspend-on-idle.c               |  4 +-
>  src/modules/module-systemd-login.c                 |  8 ++--
>  src/modules/module-udev-detect.c                   |  4 +-
>  src/modules/module-zeroconf-discover.c             |  6 +--
>  src/modules/module-zeroconf-publish.c              |  6 +--
>  src/modules/raop/module-raop-discover.c            |  6 +--
>  src/modules/rtp/headerlist.c                       |  4 +-
>  src/modules/rtp/module-rtp-recv.c                  |  8 ++--
>  src/pulse/context.c                                |  4 +-
>  src/pulse/proplist.c                               |  6 +--
>  src/pulse/stream.c                                 |  3 +-
>  src/pulsecore/card.c                               |  8 ++--
>  src/pulsecore/core.c                               |  4 +-
>  src/pulsecore/database-simple.c                    | 10 ++---
>  src/pulsecore/device-port.c                        |  2 +-
>  src/pulsecore/hashmap.c                            | 29 +++++++------
>  src/pulsecore/hashmap.h                            | 14 +++----
>  src/pulsecore/memblock.c                           | 10 ++---
>  src/pulsecore/modargs.c                            |  4 +-
>  src/pulsecore/mutex-win32.c                        |  4 +-
>  src/pulsecore/namereg.c                            |  2 +-
>  src/pulsecore/protocol-dbus.c                      | 34 +++++++--------
>  src/pulsecore/protocol-native.c                    |  4 +-
>  src/pulsecore/shared.c                             |  2 +-
>  src/pulsecore/sink-input.c                         | 12 +++---
>  src/pulsecore/sink.c                               | 10 ++---
>  src/pulsecore/source.c                             | 10 ++---
>  44 files changed, 198 insertions(+), 194 deletions(-)
> 
> diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
> index 545ae9f..fe5b7b1 100644
> --- a/src/modules/alsa/alsa-mixer.c
> +++ b/src/modules/alsa/alsa-mixer.c
> @@ -530,7 +530,7 @@ void pa_alsa_path_set_free(pa_alsa_path_set *ps) {
>      pa_assert(ps);
>  
>      if (ps->paths)
> -        pa_hashmap_free(ps->paths, NULL);
> +        pa_hashmap_free(ps->paths, NULL, NULL);
>  
>      pa_xfree(ps);
>  }
> @@ -3237,7 +3237,7 @@ static void path_set_condense(pa_alsa_path_set *ps, snd_mixer_t *m) {
>  
>              if (is_subset) {
>                  pa_log_debug("Removing path '%s' as it is a subset of '%s'.", p->name, p2->name);
> -                pa_hashmap_remove(ps->paths, p);
> +                pa_hashmap_remove(ps->paths, p, NULL);
>                  break;
>              }
>          }
> @@ -3337,19 +3337,19 @@ void pa_alsa_profile_set_free(pa_alsa_profile_set *ps) {
>      pa_assert(ps);
>  
>      if (ps->input_paths)
> -        pa_hashmap_free(ps->input_paths, (pa_free_cb_t) pa_alsa_path_free);
> +        pa_hashmap_free(ps->input_paths, NULL, (pa_free_cb_t) pa_alsa_path_free);
>  
>      if (ps->output_paths)
> -        pa_hashmap_free(ps->output_paths, (pa_free_cb_t) pa_alsa_path_free);
> +        pa_hashmap_free(ps->output_paths, NULL, (pa_free_cb_t) pa_alsa_path_free);
>  
>      if (ps->profiles)
> -        pa_hashmap_free(ps->profiles, (pa_free_cb_t) profile_free);
> +        pa_hashmap_free(ps->profiles, NULL, (pa_free_cb_t) profile_free);
>  
>      if (ps->mappings)
> -        pa_hashmap_free(ps->mappings, (pa_free_cb_t) mapping_free);
> +        pa_hashmap_free(ps->mappings, NULL, (pa_free_cb_t) mapping_free);
>  
>      if (ps->decibel_fixes)
> -        pa_hashmap_free(ps->decibel_fixes, (pa_free_cb_t) decibel_fix_free);
> +        pa_hashmap_free(ps->decibel_fixes, NULL, (pa_free_cb_t) decibel_fix_free);
>  
>      pa_xfree(ps);
>  }
> @@ -3776,13 +3776,13 @@ static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile,
>      mixer_handle = pa_alsa_open_mixer_for_pcm(pcm_handle, NULL, &hctl_handle);
>      if (!mixer_handle || !hctl_handle) {
>           /* Cannot open mixer, remove all entries */
> -        pa_hashmap_remove_all(ps->paths, NULL);
> +        pa_hashmap_remove_all(ps->paths, NULL, NULL);
>          return;
>      }
>  
>      PA_HASHMAP_FOREACH(p, ps->paths, state) {
>          if (pa_alsa_path_probe(p, mixer_handle, hctl_handle, m->profile_set->ignore_dB) < 0) {
> -            pa_hashmap_remove(ps->paths, p);
> +            pa_hashmap_remove(ps->paths, p, NULL);
>          }
>      }
>  
> @@ -4290,7 +4290,7 @@ static void paths_drop_unsupported(pa_hashmap* h) {
>      p = pa_hashmap_iterate(h, &state, &key);
>      while (p) {
>          if (p->supported <= 0) {
> -            pa_hashmap_remove(h, key);
> +            pa_hashmap_remove(h, key, NULL);
>              pa_alsa_path_free(p);
>          }
>          p = pa_hashmap_iterate(h, &state, &key);
> @@ -4420,8 +4420,8 @@ void pa_alsa_profile_set_probe(
>  
>      paths_drop_unsupported(ps->input_paths);
>      paths_drop_unsupported(ps->output_paths);
> -    pa_hashmap_free(broken_inputs, NULL);
> -    pa_hashmap_free(broken_outputs, NULL);
> +    pa_hashmap_free(broken_inputs, NULL, NULL);
> +    pa_hashmap_free(broken_outputs, NULL, NULL);
>  
>      ps->probed = true;
>  }
> @@ -4460,14 +4460,14 @@ void pa_alsa_profile_set_drop_unsupported(pa_alsa_profile_set *ps) {
>  
>      PA_HASHMAP_FOREACH(p, ps->profiles, state) {
>          if (!p->supported) {
> -            pa_hashmap_remove(ps->profiles, p->name);
> +            pa_hashmap_remove(ps->profiles, p->name, NULL);
>              profile_free(p);
>          }
>      }
>  
>      PA_HASHMAP_FOREACH(m, ps->mappings, state) {
>          if (m->supported <= 0) {
> -            pa_hashmap_remove(ps->mappings, m->name);
> +            pa_hashmap_remove(ps->mappings, m->name, NULL);
>              mapping_free(m);
>          }
>      }
> diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
> index d0294e8..d242fc8 100644
> --- a/src/modules/alsa/module-alsa-card.c
> +++ b/src/modules/alsa/module-alsa-card.c
> @@ -871,7 +871,7 @@ void pa__done(pa_module*m) {
>      if (u->mixer_handle)
>          snd_mixer_close(u->mixer_handle);
>      if (u->jacks)
> -        pa_hashmap_free(u->jacks, NULL);
> +        pa_hashmap_free(u->jacks, NULL, NULL);
>  
>      if (u->card && u->card->sinks)
>          pa_idxset_remove_all(u->card->sinks, (pa_free_cb_t) pa_alsa_sink_free);
> diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
> index dd280cb..4b0f67e 100644
> --- a/src/modules/bluetooth/bluetooth-util.c
> +++ b/src/modules/bluetooth/bluetooth-util.c
> @@ -262,7 +262,7 @@ static void device_free(pa_bluetooth_device *d) {
>              continue;
>  
>          d->transports[i] = NULL;
> -        pa_hashmap_remove(d->discovery->transports, t->path);
> +        pa_hashmap_remove(d->discovery->transports, t->path, NULL);
>          t->state = PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED;
>          pa_hook_fire(&d->discovery->hooks[PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED], t);
>          transport_free(t);
> @@ -675,7 +675,7 @@ static void remove_all_devices(pa_bluetooth_discovery *y) {
>  
>      pa_assert(y);
>  
> -    while ((d = pa_hashmap_steal_first(y->devices))) {
> +    while ((d = pa_hashmap_steal_first(y->devices, NULL))) {
>          run_callback(d, true);
>          device_free(d);
>      }
> @@ -1172,7 +1172,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
>  
>          pa_log_debug("Device %s removed", path);
>  
> -        if ((d = pa_hashmap_remove(y->devices, path))) {
> +        if ((d = pa_hashmap_remove(y->devices, path, NULL))) {
>              run_callback(d, true);
>              device_free(d);
>          }
> @@ -1327,7 +1327,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
>              if (pa_streq(interface, "org.bluez.Device1")) {
>                  pa_bluetooth_device *d;
>  
> -                if (!(d = pa_hashmap_remove(y->devices, path)))
> +                if (!(d = pa_hashmap_remove(y->devices, path, NULL)))
>                      pa_log_warn("Unknown device removed %s", path);
>                  else {
>                      pa_log_debug("Device %s removed", path);
> @@ -1772,7 +1772,7 @@ static DBusMessage *endpoint_clear_configuration(DBusConnection *c, DBusMessage
>  
>          pa_log_debug("Clearing transport %s profile %d", t->path, t->profile);
>          t->device->transports[t->profile] = NULL;
> -        pa_hashmap_remove(y->transports, t->path);
> +        pa_hashmap_remove(y->transports, t->path, NULL);
>          t->state = PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED;
>          pa_hook_fire(&y->hooks[PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED], t);
>  
> @@ -2109,12 +2109,12 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) {
>  
>      if (y->devices) {
>          remove_all_devices(y);
> -        pa_hashmap_free(y->devices, NULL);
> +        pa_hashmap_free(y->devices, NULL, NULL);
>      }
>  
>      if (y->transports) {
>          pa_assert(pa_hashmap_isempty(y->transports));
> -        pa_hashmap_free(y->transports, NULL);
> +        pa_hashmap_free(y->transports, NULL, NULL);
>      }
>  
>      if (y->connection) {
> diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
> index cbd56cc..496cc64 100644
> --- a/src/modules/bluetooth/module-bluetooth-discover.c
> +++ b/src/modules/bluetooth/module-bluetooth-discover.c
> @@ -115,7 +115,7 @@ static pa_hook_result_t load_module_for_device(pa_bluetooth_discovery *y, const
>              /* Hmm, disconnection? Then the module unloads itself */
>  
>              pa_log_debug("Unregistering module for %s", d->path);
> -            pa_hashmap_remove(u->hashmap, mi->path);
> +            pa_hashmap_remove(u->hashmap, mi->path, NULL);
>              pa_xfree(mi->path);
>              pa_xfree(mi);
>          }
> @@ -179,12 +179,12 @@ void pa__done(pa_module* m) {
>      if (u->hashmap) {
>          struct module_info *mi;
>  
> -        while ((mi = pa_hashmap_steal_first(u->hashmap))) {
> +        while ((mi = pa_hashmap_steal_first(u->hashmap, NULL))) {
>              pa_xfree(mi->path);
>              pa_xfree(mi);
>          }
>  
> -        pa_hashmap_free(u->hashmap, NULL);
> +        pa_hashmap_free(u->hashmap, NULL, NULL);
>      }
>  
>      if (u->modargs)
> diff --git a/src/modules/bluetooth/module-bluetooth-proximity.c b/src/modules/bluetooth/module-bluetooth-proximity.c
> index c4e6ca6..24b4f55 100644
> --- a/src/modules/bluetooth/module-bluetooth-proximity.c
> +++ b/src/modules/bluetooth/module-bluetooth-proximity.c
> @@ -167,7 +167,7 @@ static void io_event_cb(
>      if ((r = read(fd, &x, 1)) <= 0) {
>          pa_log_warn("Child watching '%s' died abnormally: %s", b->address, r == 0 ? "EOF" : pa_cstrerror(errno));
>  
> -        pa_assert_se(pa_hashmap_remove(b->userdata->bondings, b->address) == b);
> +        pa_assert_se(pa_hashmap_remove(b->userdata->bondings, b->address, NULL) == b);
>          bonding_free(b);
>          return;
>      }
> @@ -280,7 +280,7 @@ static void bonding_remove(struct userdata *u, const char *a) {
>      struct bonding *b;
>      pa_assert(u);
>  
> -    pa_return_if_fail((b = pa_hashmap_remove(u->bondings, a)));
> +    pa_return_if_fail((b = pa_hashmap_remove(u->bondings, a, NULL)));
>  
>      pa_log_info("No longer watching device '%s'", b->address);
>      bonding_free(b);
> @@ -466,7 +466,7 @@ void pa__done(pa_module*m) {
>          return;
>  
>      if (u->bondings)
> -        pa_hashmap_free(u->bondings, (pa_free_cb_t) bonding_free);
> +        pa_hashmap_free(u->bondings, NULL, (pa_free_cb_t) bonding_free);
>  
>      if (u->dbus_connection) {
>          update_matches(u, false);
> diff --git a/src/modules/dbus/iface-card.c b/src/modules/dbus/iface-card.c
> index 19dd4ed..49a0abf 100644
> --- a/src/modules/dbus/iface-card.c
> +++ b/src/modules/dbus/iface-card.c
> @@ -495,7 +495,7 @@ static pa_hook_result_t card_profile_added_cb(void *hook_data, void *call_data,
>          return PA_HOOK_OK;
>  
>      p = pa_dbusiface_card_profile_new(c, core, profile, c->next_profile_index++);
> -    pa_assert_se(pa_hashmap_put(c->profiles, pa_dbusiface_card_profile_get_name(p), p) >= 0);
> +    pa_assert_se(pa_hashmap_put(c->profiles, (char *) pa_dbusiface_card_profile_get_name(p), p) >= 0);
>  
>      /* Send D-Bus signal */
>      object_path = pa_dbusiface_card_profile_get_path(p);
> @@ -532,7 +532,7 @@ pa_dbusiface_card *pa_dbusiface_card_new(pa_dbusiface_core *core, pa_card *card)
>  
>      PA_HASHMAP_FOREACH(profile, card->profiles, state) {
>          pa_dbusiface_card_profile *p = pa_dbusiface_card_profile_new(c, card->core, profile, c->next_profile_index++);
> -        pa_hashmap_put(c->profiles, pa_dbusiface_card_profile_get_name(p), p);
> +        pa_hashmap_put(c->profiles, (char *) pa_dbusiface_card_profile_get_name(p), p);
>      }
>  
>      pa_assert_se(pa_dbus_protocol_add_interface(c->dbus_protocol, c->path, &card_interface_info, c) >= 0);
> @@ -550,7 +550,7 @@ void pa_dbusiface_card_free(pa_dbusiface_card *c) {
>  
>      pa_hook_slot_free(c->card_profile_added_slot);
>  
> -    pa_hashmap_free(c->profiles, (pa_free_cb_t) pa_dbusiface_card_profile_free);
> +    pa_hashmap_free(c->profiles, NULL, (pa_free_cb_t) pa_dbusiface_card_profile_free);
>      pa_proplist_free(c->proplist);
>      pa_dbus_protocol_unref(c->dbus_protocol);
>      pa_subscription_free(c->subscription);
> diff --git a/src/modules/dbus/iface-core.c b/src/modules/dbus/iface-core.c
> index edc22ab..c1c968b 100644
> --- a/src/modules/dbus/iface-core.c
> +++ b/src/modules/dbus/iface-core.c
> @@ -1665,7 +1665,7 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
>                  pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
>  
>              } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
> -                if (!(card_iface = pa_hashmap_remove(c->cards, PA_UINT32_TO_PTR(idx))))
> +                if (!(card_iface = pa_hashmap_remove(c->cards, PA_UINT32_TO_PTR(idx), NULL)))
>                      return;
>  
>                  object_path = pa_dbusiface_card_get_path(card_iface);
> @@ -1699,7 +1699,7 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
>                  pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
>  
>              } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
> -                if (!(stream_iface = pa_hashmap_remove(c->playback_streams, PA_UINT32_TO_PTR(idx))))
> +                if (!(stream_iface = pa_hashmap_remove(c->playback_streams, PA_UINT32_TO_PTR(idx), NULL)))
>                      return;
>  
>                  object_path = pa_dbusiface_stream_get_path(stream_iface);
> @@ -1733,7 +1733,7 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
>                  pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
>  
>              } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
> -                if (!(stream_iface = pa_hashmap_remove(c->record_streams, PA_UINT32_TO_PTR(idx))))
> +                if (!(stream_iface = pa_hashmap_remove(c->record_streams, PA_UINT32_TO_PTR(idx), NULL)))
>                      return;
>  
>                  object_path = pa_dbusiface_stream_get_path(stream_iface);
> @@ -1767,7 +1767,7 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
>                  pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
>  
>              } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
> -                if (!(sample_iface = pa_hashmap_remove(c->samples, PA_UINT32_TO_PTR(idx))))
> +                if (!(sample_iface = pa_hashmap_remove(c->samples, PA_UINT32_TO_PTR(idx), NULL)))
>                      return;
>  
>                  object_path = pa_dbusiface_sample_get_path(sample_iface);
> @@ -1801,7 +1801,7 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
>                  pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
>  
>              } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
> -                if (!(module_iface = pa_hashmap_remove(c->modules, PA_UINT32_TO_PTR(idx))))
> +                if (!(module_iface = pa_hashmap_remove(c->modules, PA_UINT32_TO_PTR(idx), NULL)))
>                      return;
>  
>                  object_path = pa_dbusiface_module_get_path(module_iface);
> @@ -1835,7 +1835,7 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
>                  pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
>  
>              } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
> -                if (!(client_iface = pa_hashmap_remove(c->clients, PA_UINT32_TO_PTR(idx))))
> +                if (!(client_iface = pa_hashmap_remove(c->clients, PA_UINT32_TO_PTR(idx), NULL)))
>                      return;
>  
>                  object_path = pa_dbusiface_client_get_path(client_iface);
> @@ -1870,7 +1870,7 @@ static pa_hook_result_t sink_put_cb(void *hook_data, void *call_data, void *slot
>      object_path = pa_dbusiface_device_get_path(d);
>  
>      pa_assert_se(pa_hashmap_put(c->sinks_by_index, PA_UINT32_TO_PTR(s->index), d) >= 0);
> -    pa_assert_se(pa_hashmap_put(c->sinks_by_path, object_path, d) >= 0);
> +    pa_assert_se(pa_hashmap_put(c->sinks_by_path, (char *) object_path, d) >= 0);
>  
>      pa_assert_se(signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
>                                                        PA_DBUS_CORE_INTERFACE,
> @@ -1893,9 +1893,9 @@ static pa_hook_result_t sink_unlink_cb(void *hook_data, void *call_data, void *s
>      pa_assert(c);
>      pa_assert(s);
>  
> -    pa_assert_se(d = pa_hashmap_remove(c->sinks_by_index, PA_UINT32_TO_PTR(s->index)));
> +    pa_assert_se(d = pa_hashmap_remove(c->sinks_by_index, PA_UINT32_TO_PTR(s->index), NULL));
>      object_path = pa_dbusiface_device_get_path(d);
> -    pa_assert_se(pa_hashmap_remove(c->sinks_by_path, object_path));
> +    pa_assert_se(pa_hashmap_remove(c->sinks_by_path, object_path, NULL));
>  
>      pa_assert_se(signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
>                                                        PA_DBUS_CORE_INTERFACE,
> @@ -1924,7 +1924,7 @@ static pa_hook_result_t source_put_cb(void *hook_data, void *call_data, void *sl
>      object_path = pa_dbusiface_device_get_path(d);
>  
>      pa_assert_se(pa_hashmap_put(c->sources_by_index, PA_UINT32_TO_PTR(s->index), d) >= 0);
> -    pa_assert_se(pa_hashmap_put(c->sources_by_path, object_path, d) >= 0);
> +    pa_assert_se(pa_hashmap_put(c->sources_by_path, (char *) object_path, d) >= 0);
>  
>      pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
>                                                         PA_DBUS_CORE_INTERFACE,
> @@ -1947,9 +1947,9 @@ static pa_hook_result_t source_unlink_cb(void *hook_data, void *call_data, void
>      pa_assert(c);
>      pa_assert(s);
>  
> -    pa_assert_se(d = pa_hashmap_remove(c->sources_by_index, PA_UINT32_TO_PTR(s->index)));
> +    pa_assert_se(d = pa_hashmap_remove(c->sources_by_index, PA_UINT32_TO_PTR(s->index), NULL));
>      object_path = pa_dbusiface_device_get_path(d);
> -    pa_assert_se(pa_hashmap_remove(c->sources_by_path, object_path));
> +    pa_assert_se(pa_hashmap_remove(c->sources_by_path, object_path, NULL));
>  
>      pa_assert_se(signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
>                                                        PA_DBUS_CORE_INTERFACE,
> @@ -2060,13 +2060,13 @@ pa_dbusiface_core *pa_dbusiface_core_new(pa_core *core) {
>      PA_IDXSET_FOREACH(sink, core->sinks, idx) {
>          device = pa_dbusiface_device_new_sink(c, sink);
>          pa_hashmap_put(c->sinks_by_index, PA_UINT32_TO_PTR(idx), device);
> -        pa_hashmap_put(c->sinks_by_path, pa_dbusiface_device_get_path(device), device);
> +        pa_hashmap_put(c->sinks_by_path, (char *) pa_dbusiface_device_get_path(device), device);
>      }
>  
>      PA_IDXSET_FOREACH(source, core->sources, idx) {
>          device = pa_dbusiface_device_new_source(c, source);
>          pa_hashmap_put(c->sources_by_index, PA_UINT32_TO_PTR(idx), device);
> -        pa_hashmap_put(c->sources_by_path, pa_dbusiface_device_get_path(device), device);
> +        pa_hashmap_put(c->sources_by_path, (char *) pa_dbusiface_device_get_path(device), device);
>      }
>  
>      PA_IDXSET_FOREACH(sink_input, core->sink_inputs, idx)
> @@ -2097,16 +2097,16 @@ void pa_dbusiface_core_free(pa_dbusiface_core *c) {
>      /* Note that the order of freeing is important below.
>       * Do not change it for the sake of tidiness without checking! */
>      pa_subscription_free(c->subscription);
> -    pa_hashmap_free(c->cards, (pa_free_cb_t) pa_dbusiface_card_free);
> -    pa_hashmap_free(c->sinks_by_path, NULL);
> -    pa_hashmap_free(c->sinks_by_index, (pa_free_cb_t) pa_dbusiface_device_free);
> -    pa_hashmap_free(c->sources_by_path, NULL);
> -    pa_hashmap_free(c->sources_by_index, (pa_free_cb_t) pa_dbusiface_device_free);
> -    pa_hashmap_free(c->playback_streams, (pa_free_cb_t) pa_dbusiface_stream_free);
> -    pa_hashmap_free(c->record_streams, (pa_free_cb_t) pa_dbusiface_stream_free);
> -    pa_hashmap_free(c->samples, (pa_free_cb_t) pa_dbusiface_sample_free);
> -    pa_hashmap_free(c->modules, (pa_free_cb_t) pa_dbusiface_module_free);
> -    pa_hashmap_free(c->clients, (pa_free_cb_t) pa_dbusiface_client_free);
> +    pa_hashmap_free(c->cards, NULL, (pa_free_cb_t) pa_dbusiface_card_free);
> +    pa_hashmap_free(c->sinks_by_path, NULL, NULL);
> +    pa_hashmap_free(c->sinks_by_index, NULL, (pa_free_cb_t) pa_dbusiface_device_free);
> +    pa_hashmap_free(c->sources_by_path, NULL, NULL);
> +    pa_hashmap_free(c->sources_by_index, NULL, (pa_free_cb_t) pa_dbusiface_device_free);
> +    pa_hashmap_free(c->playback_streams, NULL, (pa_free_cb_t) pa_dbusiface_stream_free);
> +    pa_hashmap_free(c->record_streams, NULL, (pa_free_cb_t) pa_dbusiface_stream_free);
> +    pa_hashmap_free(c->samples, NULL, (pa_free_cb_t) pa_dbusiface_sample_free);
> +    pa_hashmap_free(c->modules, NULL, (pa_free_cb_t) pa_dbusiface_module_free);
> +    pa_hashmap_free(c->clients, NULL, (pa_free_cb_t) pa_dbusiface_client_free);
>      pa_hook_slot_free(c->sink_put_slot);
>      pa_hook_slot_free(c->sink_unlink_slot);
>      pa_hook_slot_free(c->source_put_slot);
> diff --git a/src/modules/dbus/iface-device.c b/src/modules/dbus/iface-device.c
> index 4af0333..f99512e 100644
> --- a/src/modules/dbus/iface-device.c
> +++ b/src/modules/dbus/iface-device.c
> @@ -1223,7 +1223,7 @@ pa_dbusiface_device *pa_dbusiface_device_new_sink(pa_dbusiface_core *core, pa_si
>  
>      PA_HASHMAP_FOREACH(port, sink->ports, state) {
>          pa_dbusiface_device_port *p = pa_dbusiface_device_port_new(d, sink->core, port, d->next_port_index++);
> -        pa_hashmap_put(d->ports, pa_dbusiface_device_port_get_name(p), p);
> +        pa_hashmap_put(d->ports, (char *) pa_dbusiface_device_port_get_name(p), p);
>      }
>  
>      pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &device_interface_info, d) >= 0);
> @@ -1257,7 +1257,7 @@ pa_dbusiface_device *pa_dbusiface_device_new_source(pa_dbusiface_core *core, pa_
>  
>      PA_HASHMAP_FOREACH(port, source->ports, state) {
>          pa_dbusiface_device_port *p = pa_dbusiface_device_port_new(d, source->core, port, d->next_port_index++);
> -        pa_hashmap_put(d->ports, pa_dbusiface_device_port_get_name(p), p);
> +        pa_hashmap_put(d->ports, (char *) pa_dbusiface_device_port_get_name(p), p);
>      }
>  
>      pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &device_interface_info, d) >= 0);
> @@ -1279,7 +1279,7 @@ void pa_dbusiface_device_free(pa_dbusiface_device *d) {
>          pa_assert_se(pa_dbus_protocol_remove_interface(d->dbus_protocol, d->path, source_interface_info.name) >= 0);
>          pa_source_unref(d->source);
>      }
> -    pa_hashmap_free(d->ports, (pa_free_cb_t) pa_dbusiface_device_port_free);
> +    pa_hashmap_free(d->ports, NULL, (pa_free_cb_t) pa_dbusiface_device_port_free);
>      pa_proplist_free(d->proplist);
>      pa_dbus_protocol_unref(d->dbus_protocol);
>      pa_subscription_free(d->subscription);
> diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c
> index 448fde5..c43d549 100644
> --- a/src/modules/gconf/module-gconf.c
> +++ b/src/modules/gconf/module-gconf.c
> @@ -290,7 +290,7 @@ static int handle_event(struct userdata *u) {
>                      goto fail;
>  
>                  if ((m = pa_hashmap_get(u->module_infos, name))) {
> -                    pa_hashmap_remove(u->module_infos, name);
> +                    pa_hashmap_remove(u->module_infos, name, NULL);
>                      module_info_free(m);
>                  }
>  
> @@ -401,7 +401,7 @@ void pa__done(pa_module*m) {
>          pa_close(u->fd);
>  
>      if (u->module_infos)
> -        pa_hashmap_free(u->module_infos, (pa_free_cb_t) module_info_free);
> +        pa_hashmap_free(u->module_infos, NULL, (pa_free_cb_t) module_info_free);
>  
>      pa_xfree(u);
>  }
> diff --git a/src/modules/macosx/module-bonjour-publish.c b/src/modules/macosx/module-bonjour-publish.c
> index 26081ec..a172c34 100644
> --- a/src/modules/macosx/module-bonjour-publish.c
> +++ b/src/modules/macosx/module-bonjour-publish.c
> @@ -321,7 +321,7 @@ static struct service *get_service(struct userdata *u, pa_object *device) {
>  static void service_free(struct service *s) {
>      pa_assert(s);
>  
> -    pa_hashmap_remove(s->userdata->services, s->device);
> +    pa_hashmap_remove(s->userdata->services, s->device, NULL);
>  
>      if (s->service)
>          DNSServiceRefDeallocate(s->service);
> @@ -490,7 +490,7 @@ void pa__done(pa_module*m) {
>      unpublish_all_services(u);
>  
>      if (u->services)
> -        pa_hashmap_free(u->services, NULL);
> +        pa_hashmap_free(u->services, NULL, NULL);
>  
>      if (u->sink_new_slot)
>          pa_hook_slot_free(u->sink_new_slot);
> diff --git a/src/modules/module-augment-properties.c b/src/modules/module-augment-properties.c
> index fcc3462..1c9f7a4 100644
> --- a/src/modules/module-augment-properties.c
> +++ b/src/modules/module-augment-properties.c
> @@ -246,7 +246,7 @@ static void make_room(pa_hashmap *cache) {
>      while (pa_hashmap_size(cache) >= MAX_CACHE_SIZE) {
>          struct rule *r;
>  
> -        pa_assert_se(r = pa_hashmap_steal_first(cache));
> +        pa_assert_se(r = pa_hashmap_steal_first(cache, NULL));
>          rule_free(r);
>      }
>  }
> @@ -348,7 +348,7 @@ void pa__done(pa_module *m) {
>          pa_hook_slot_free(u->client_proplist_changed_slot);
>  
>      if (u->cache)
> -        pa_hashmap_free(u->cache, (pa_free_cb_t) rule_free);
> +        pa_hashmap_free(u->cache, NULL, (pa_free_cb_t) rule_free);
>  
>      pa_xfree(u);
>  }
> diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c
> index 928f153..429a462 100644
> --- a/src/modules/module-card-restore.c
> +++ b/src/modules/module-card-restore.c
> @@ -137,7 +137,7 @@ static void entry_free(struct entry* e) {
>      pa_assert(e);
>  
>      pa_xfree(e->profile);
> -    pa_hashmap_free(e->ports, (pa_free_cb_t) port_info_free);
> +    pa_hashmap_free(e->ports, NULL, (pa_free_cb_t) port_info_free);
>  
>      pa_xfree(e);
>  }
> diff --git a/src/modules/module-console-kit.c b/src/modules/module-console-kit.c
> index 007d23b..c00d5c3 100644
> --- a/src/modules/module-console-kit.c
> +++ b/src/modules/module-console-kit.c
> @@ -146,7 +146,7 @@ static void free_session(struct session *session) {
>  static void remove_session(struct userdata *u, const char *id) {
>      struct session *session;
>  
> -    if (!(session = pa_hashmap_remove(u->sessions, id)))
> +    if (!(session = pa_hashmap_remove(u->sessions, id, NULL)))
>          return;
>  
>      free_session(session);
> @@ -346,7 +346,7 @@ void pa__done(pa_module *m) {
>          return;
>  
>      if (u->sessions)
> -        pa_hashmap_free(u->sessions, (pa_free_cb_t) free_session);
> +        pa_hashmap_free(u->sessions, NULL, (pa_free_cb_t) free_session);
>  
>      if (u->connection) {
>          pa_dbus_remove_matches(
> diff --git a/src/modules/module-device-manager.c b/src/modules/module-device-manager.c
> index 6ae9cee..b818f9b 100644
> --- a/src/modules/module-device-manager.c
> +++ b/src/modules/module-device-manager.c
> @@ -1306,24 +1306,24 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
>          for (i = 0; i < n_devices; ++i) {
>              const char *s;
>              if (pa_tagstruct_gets(t, &s) < 0) {
> -                while ((device = pa_hashmap_steal_first(h))) {
> +                while ((device = pa_hashmap_steal_first(h, NULL))) {
>                      pa_xfree(device->device);
>                      pa_xfree(device);
>                  }
>  
> -                pa_hashmap_free(h, NULL);
> +                pa_hashmap_free(h, NULL, NULL);
>                  pa_log_error("Protocol error on reorder");
>                  goto fail;
>              }
>  
>              /* Ensure this is a valid entry */
>              if (!(e = entry_read(u, s))) {
> -                while ((device = pa_hashmap_steal_first(h))) {
> +                while ((device = pa_hashmap_steal_first(h, NULL))) {
>                      pa_xfree(device->device);
>                      pa_xfree(device);
>                  }
>  
> -                pa_hashmap_free(h, NULL);
> +                pa_hashmap_free(h, NULL, NULL);
>                  pa_log_error("Client specified an unknown device in it's reorder list.");
>                  goto fail;
>              }
> @@ -1333,12 +1333,12 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
>                  first = false;
>                  sink_mode = (0 == strncmp("sink:", s, 5));
>              } else if ((sink_mode && 0 != strncmp("sink:", s, 5)) || (!sink_mode && 0 != strncmp("source:", s, 7))) {
> -                while ((device = pa_hashmap_steal_first(h))) {
> +                while ((device = pa_hashmap_steal_first(h, NULL))) {
>                      pa_xfree(device->device);
>                      pa_xfree(device);
>                  }
>  
> -                pa_hashmap_free(h, NULL);
> +                pa_hashmap_free(h, NULL, NULL);
>                  pa_log_error("Attempted to reorder mixed devices (sinks and sources)");
>                  goto fail;
>              }
> @@ -1408,10 +1408,10 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
>          n_devices = pa_hashmap_size(h);
>          devices = pa_xnew(struct device_t *,  n_devices);
>          idx = 0;
> -        while ((device = pa_hashmap_steal_first(h))) {
> +        while ((device = pa_hashmap_steal_first(h, NULL))) {
>              devices[idx++] = device;
>          }
> -        pa_hashmap_free(h, NULL);
> +        pa_hashmap_free(h, NULL, NULL);
>  
>          /* Simple bubble sort */
>          for (i = 0; i < n_devices; ++i) {
> diff --git a/src/modules/module-filter-apply.c b/src/modules/module-filter-apply.c
> index 05d4284..4e58890 100644
> --- a/src/modules/module-filter-apply.c
> +++ b/src/modules/module-filter-apply.c
> @@ -262,7 +262,7 @@ static void housekeeping_time_callback(pa_mainloop_api*a, pa_time_event* e, cons
>  
>              pa_log_debug("Detected filter %s as no longer used. Unloading.", filter->name);
>              idx = filter->module_index;
> -            pa_hashmap_remove(u->filters, filter);
> +            pa_hashmap_remove(u->filters, filter, NULL);
>              filter_free(filter);
>              pa_module_unload_request_by_index(u->core, idx, true);
>          }
> @@ -577,7 +577,7 @@ static pa_hook_result_t sink_unlink_cb(pa_core *core, pa_sink *sink, struct user
>              }
>  
>              idx = filter->module_index;
> -            pa_hashmap_remove(u->filters, filter);
> +            pa_hashmap_remove(u->filters, filter, NULL);
>              filter_free(filter);
>  
>              if (can_unload_module(u, idx))
> @@ -649,7 +649,7 @@ static pa_hook_result_t source_unlink_cb(pa_core *core, pa_source *source, struc
>              }
>  
>              idx = filter->module_index;
> -            pa_hashmap_remove(u->filters, filter);
> +            pa_hashmap_remove(u->filters, filter, NULL);
>              filter_free(filter);
>  
>              if (can_unload_module(u, idx))
> @@ -742,12 +742,12 @@ void pa__done(pa_module *m) {
>      if (u->filters) {
>          struct filter *f;
>  
> -        while ((f = pa_hashmap_steal_first(u->filters))) {
> +        while ((f = pa_hashmap_steal_first(u->filters, NULL))) {
>              pa_module_unload_request_by_index(u->core, f->module_index, true);
>              filter_free(f);
>          }
>  
> -        pa_hashmap_free(u->filters, NULL);
> +        pa_hashmap_free(u->filters, NULL, NULL);
>      }
>  
>      pa_xfree(u);
> diff --git a/src/modules/module-role-cork.c b/src/modules/module-role-cork.c
> index 9906d2e..74a9243 100644
> --- a/src/modules/module-role-cork.c
> +++ b/src/modules/module-role-cork.c
> @@ -129,7 +129,7 @@ static inline void apply_cork_to_sink(struct userdata *u, pa_sink *s, pa_sink_in
>              pa_sink_input_set_mute(j, true, false);
>              pa_sink_input_send_event(j, PA_STREAM_EVENT_REQUEST_CORK, NULL);
>          } else if (!cork) {
> -            pa_hashmap_remove(u->cork_state, j);
> +            pa_hashmap_remove(u->cork_state, j, NULL);
>  
>              if (corked_here && (corked || muted)) {
>                  pa_log_debug("Found a '%s' stream that should be uncorked/unmuted.", cork_role);
> @@ -161,7 +161,7 @@ static pa_hook_result_t process(struct userdata *u, pa_sink_input *i, bool creat
>      pa_sink_input_assert_ref(i);
>  
>      if (!create)
> -        pa_hashmap_remove(u->cork_state, i);
> +        pa_hashmap_remove(u->cork_state, i, NULL);
>  
>      if (!(role = pa_proplist_gets(i->proplist, PA_PROP_MEDIA_ROLE)))
>          return PA_HOOK_OK;
> @@ -304,7 +304,7 @@ void pa__done(pa_module *m) {
>          pa_hook_slot_free(u->sink_input_move_finish_slot);
>  
>      if (u->cork_state)
> -        pa_hashmap_free(u->cork_state, NULL);
> +        pa_hashmap_free(u->cork_state, NULL, NULL);
>  
>      pa_xfree(u);
>  
> diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c
> index 735dcde..b2ce102 100644
> --- a/src/modules/module-stream-restore.c
> +++ b/src/modules/module-stream-restore.c
> @@ -949,7 +949,7 @@ static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *us
>      send_entry_removed_signal(de);
>      trigger_save(de->userdata);
>  
> -    pa_assert_se(pa_hashmap_remove(de->userdata->dbus_entries, de->entry_name));
> +    pa_assert_se(pa_hashmap_remove(de->userdata->dbus_entries, de->entry_name, NULL));
>      dbus_entry_free(de);
>  
>      pa_dbus_send_empty_reply(conn, msg);
> @@ -2099,7 +2099,7 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
>  
>                  PA_HASHMAP_FOREACH(de, u->dbus_entries, state) {
>                      send_entry_removed_signal(de);
> -                    dbus_entry_free(pa_hashmap_remove(u->dbus_entries, de->entry_name));
> +                    dbus_entry_free(pa_hashmap_remove(u->dbus_entries, de->entry_name, NULL));
>                  }
>  #endif
>                  pa_database_clear(u->database);
> @@ -2211,7 +2211,7 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
>  #ifdef HAVE_DBUS
>                  if ((de = pa_hashmap_get(u->dbus_entries, name))) {
>                      send_entry_removed_signal(de);
> -                    dbus_entry_free(pa_hashmap_remove(u->dbus_entries, name));
> +                    dbus_entry_free(pa_hashmap_remove(u->dbus_entries, name, NULL));
>                  }
>  #endif
>  
> @@ -2507,7 +2507,7 @@ void pa__done(pa_module*m) {
>          pa_assert_se(pa_dbus_protocol_unregister_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0);
>          pa_assert_se(pa_dbus_protocol_remove_interface(u->dbus_protocol, OBJECT_PATH, stream_restore_interface_info.name) >= 0);
>  
> -        pa_hashmap_free(u->dbus_entries, (pa_free_cb_t) dbus_entry_free);
> +        pa_hashmap_free(u->dbus_entries, NULL, (pa_free_cb_t) dbus_entry_free);
>  
>          pa_dbus_protocol_unref(u->dbus_protocol);
>      }
> diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
> index 6d49acb..1ef77f8 100644
> --- a/src/modules/module-suspend-on-idle.c
> +++ b/src/modules/module-suspend-on-idle.c
> @@ -376,7 +376,7 @@ static pa_hook_result_t device_unlink_hook_cb(pa_core *c, pa_object *o, struct u
>      pa_object_assert_ref(o);
>      pa_assert(u);
>  
> -    if ((d = pa_hashmap_remove(u->device_infos, o)))
> +    if ((d = pa_hashmap_remove(u->device_infos, o, NULL)))
>          device_info_free(d);
>  
>      return PA_HOOK_OK;
> @@ -518,7 +518,7 @@ void pa__done(pa_module*m) {
>      if (u->source_output_state_changed_slot)
>          pa_hook_slot_free(u->source_output_state_changed_slot);
>  
> -    pa_hashmap_free(u->device_infos, (pa_free_cb_t) device_info_free);
> +    pa_hashmap_free(u->device_infos, NULL, (pa_free_cb_t) device_info_free);
>  
>      pa_xfree(u);
>  }
> diff --git a/src/modules/module-systemd-login.c b/src/modules/module-systemd-login.c
> index 18f8cc5..2c60a3a 100644
> --- a/src/modules/module-systemd-login.c
> +++ b/src/modules/module-systemd-login.c
> @@ -128,7 +128,7 @@ static int get_session_list(struct userdata *u) {
>           * this here. */
>  
>          for (s = sessions; *s; s++) {
> -            o = pa_hashmap_remove(u->previous_sessions, *s);
> +            o = pa_hashmap_remove(u->previous_sessions, *s, NULL);
>              if (o)
>                  pa_hashmap_put(u->sessions, o->id, o);
>              else
> @@ -140,7 +140,7 @@ static int get_session_list(struct userdata *u) {
>          free(sessions);
>      }
>  
> -    pa_hashmap_remove_all(u->previous_sessions, (pa_free_cb_t) free_session);
> +    pa_hashmap_remove_all(u->previous_sessions, NULL, (pa_free_cb_t) free_session);
>  
>      return 0;
>  }
> @@ -219,8 +219,8 @@ void pa__done(pa_module *m) {
>          return;
>  
>      if (u->sessions) {
> -        pa_hashmap_free(u->sessions, (pa_free_cb_t) free_session);
> -        pa_hashmap_free(u->previous_sessions, (pa_free_cb_t) free_session);
> +        pa_hashmap_free(u->sessions, NULL, (pa_free_cb_t)free_session);
> +        pa_hashmap_free(u->previous_sessions, NULL, (pa_free_cb_t)free_session);
>      }
>  
>      if (u->io)
> diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c
> index fcedfcd..0dd5793 100644
> --- a/src/modules/module-udev-detect.c
> +++ b/src/modules/module-udev-detect.c
> @@ -436,7 +436,7 @@ static void remove_card(struct userdata *u, struct udev_device *dev) {
>      pa_assert(u);
>      pa_assert(dev);
>  
> -    if (!(d = pa_hashmap_remove(u->devices, udev_device_get_devpath(dev))))
> +    if (!(d = pa_hashmap_remove(u->devices, udev_device_get_devpath(dev), NULL)))
>          return;
>  
>      pa_log_info("Card %s removed.", d->path);
> @@ -841,7 +841,7 @@ void pa__done(pa_module *m) {
>          pa_close(u->inotify_fd);
>  
>      if (u->devices)
> -        pa_hashmap_free(u->devices, (pa_free_cb_t) device_free);
> +        pa_hashmap_free(u->devices, NULL, (pa_free_cb_t) device_free);
>  
>      pa_xfree(u);
>  }
> diff --git a/src/modules/module-zeroconf-discover.c b/src/modules/module-zeroconf-discover.c
> index 4ec3747..0652e9a 100644
> --- a/src/modules/module-zeroconf-discover.c
> +++ b/src/modules/module-zeroconf-discover.c
> @@ -282,7 +282,7 @@ static void browser_cb(
>  
>          if ((t2 = pa_hashmap_get(u->tunnels, t))) {
>              pa_module_unload_request_by_index(u->core, t2->module_index, true);
> -            pa_hashmap_remove(u->tunnels, t2);
> +            pa_hashmap_remove(u->tunnels, t2, NULL);
>              tunnel_free(t2);
>          }
>      }
> @@ -421,12 +421,12 @@ void pa__done(pa_module*m) {
>      if (u->tunnels) {
>          struct tunnel *t;
>  
> -        while ((t = pa_hashmap_steal_first(u->tunnels))) {
> +        while ((t = pa_hashmap_steal_first(u->tunnels, NULL))) {
>              pa_module_unload_request_by_index(u->core, t->module_index, true);
>              tunnel_free(t);
>          }
>  
> -        pa_hashmap_free(u->tunnels, NULL);
> +        pa_hashmap_free(u->tunnels, NULL, NULL);
>      }
>  
>      pa_xfree(u);
> diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c
> index 3350008..fe1f8f8 100644
> --- a/src/modules/module-zeroconf-publish.c
> +++ b/src/modules/module-zeroconf-publish.c
> @@ -374,7 +374,7 @@ finish:
>  
>      /* Remove this service */
>      if (r < 0) {
> -        pa_hashmap_remove(s->userdata->services, s->key);
> +        pa_hashmap_remove(s->userdata->services, s->key, NULL);
>          service_free(s);
>      }
>  
> @@ -474,7 +474,7 @@ static pa_hook_result_t device_unlink_cb(pa_core *c, pa_object *o, struct userda
>  
>      pa_threaded_mainloop_lock(u->mainloop);
>  
> -    if ((s = pa_hashmap_remove(u->services, o)))
> +    if ((s = pa_hashmap_remove(u->services, o, NULL)))
>          service_free(s);
>  
>      pa_threaded_mainloop_unlock(u->mainloop);
> @@ -786,7 +786,7 @@ fail:
>  static void client_free(pa_mainloop_api *api PA_GCC_UNUSED, void *userdata) {
>      struct userdata *u = (struct userdata *) userdata;
>  
> -    pa_hashmap_free(u->services, (pa_free_cb_t) service_free);
> +    pa_hashmap_free(u->services, NULL, (pa_free_cb_t) service_free);
>  
>      if (u->main_entry_group)
>          avahi_entry_group_free(u->main_entry_group);
> diff --git a/src/modules/raop/module-raop-discover.c b/src/modules/raop/module-raop-discover.c
> index c7efe9a..9ea2848 100644
> --- a/src/modules/raop/module-raop-discover.c
> +++ b/src/modules/raop/module-raop-discover.c
> @@ -257,7 +257,7 @@ static void browser_cb(
>  
>          if ((t2 = pa_hashmap_get(u->tunnels, t))) {
>              pa_module_unload_request_by_index(u->core, t2->module_index, true);
> -            pa_hashmap_remove(u->tunnels, t2);
> +            pa_hashmap_remove(u->tunnels, t2, NULL);
>              tunnel_free(t2);
>          }
>      }
> @@ -376,12 +376,12 @@ void pa__done(pa_module*m) {
>      if (u->tunnels) {
>          struct tunnel *t;
>  
> -        while ((t = pa_hashmap_steal_first(u->tunnels))) {
> +        while ((t = pa_hashmap_steal_first(u->tunnels, NULL))) {
>              pa_module_unload_request_by_index(u->core, t->module_index, true);
>              tunnel_free(t);
>          }
>  
> -        pa_hashmap_free(u->tunnels, NULL);
> +        pa_hashmap_free(u->tunnels, NULL, NULL);
>      }
>  
>      pa_xfree(u);
> diff --git a/src/modules/rtp/headerlist.c b/src/modules/rtp/headerlist.c
> index 9e95e3c..bfc97cd 100644
> --- a/src/modules/rtp/headerlist.c
> +++ b/src/modules/rtp/headerlist.c
> @@ -56,7 +56,7 @@ pa_headerlist* pa_headerlist_new(void) {
>  }
>  
>  void pa_headerlist_free(pa_headerlist* p) {
> -    pa_hashmap_free(MAKE_HASHMAP(p), (pa_free_cb_t) header_free);
> +    pa_hashmap_free(MAKE_HASHMAP(p), NULL, (pa_free_cb_t) header_free);
>  }
>  
>  int pa_headerlist_puts(pa_headerlist *p, const char *key, const char *value) {
> @@ -134,7 +134,7 @@ int pa_headerlist_remove(pa_headerlist *p, const char *key) {
>      pa_assert(p);
>      pa_assert(key);
>  
> -    if (!(hdr = pa_hashmap_remove(MAKE_HASHMAP(p), key)))
> +    if (!(hdr = pa_hashmap_remove(MAKE_HASHMAP(p), key, NULL)))
>          return -1;
>  
>      header_free(hdr);
> diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c
> index 7ff2c75..43505fa 100644
> --- a/src/modules/rtp/module-rtp-recv.c
> +++ b/src/modules/rtp/module-rtp-recv.c
> @@ -186,7 +186,7 @@ static void sink_input_kill(pa_sink_input* i) {
>      pa_sink_input_assert_ref(i);
>      pa_assert_se(s = i->userdata);
>  
> -    pa_hashmap_remove(s->userdata->by_origin, s->sdp_info.origin);
> +    pa_hashmap_remove(s->userdata->by_origin, s->sdp_info.origin, NULL);
>      session_free(s);
>  }
>  
> @@ -635,7 +635,7 @@ static void sap_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event
>  
>      if (goodbye) {
>  
> -        if ((s = pa_hashmap_remove(u->by_origin, info.origin)))
> +        if ((s = pa_hashmap_remove(u->by_origin, info.origin, NULL)))
>              session_free(s);
>  
>          pa_sdp_info_destroy(&info);
> @@ -675,7 +675,7 @@ static void check_death_event_cb(pa_mainloop_api *m, pa_time_event *t, const str
>          k = pa_atomic_load(&s->timestamp);
>  
>          if (k + DEATH_TIMEOUT < now.tv_sec) {
> -            pa_hashmap_remove(u->by_origin, s->sdp_info.origin);
> +            pa_hashmap_remove(u->by_origin, s->sdp_info.origin, NULL);
>              session_free(s);
>          }
>      }
> @@ -770,7 +770,7 @@ void pa__done(pa_module*m) {
>      pa_sap_context_destroy(&u->sap_context);
>  
>      if (u->by_origin)
> -        pa_hashmap_free(u->by_origin, (pa_free_cb_t) session_free);
> +        pa_hashmap_free(u->by_origin, NULL, (pa_free_cb_t) session_free);
>  
>      pa_xfree(u->sink_name);
>      pa_xfree(u);
> diff --git a/src/pulse/context.c b/src/pulse/context.c
> index 1ba2672..4d3cc0e 100644
> --- a/src/pulse/context.c
> +++ b/src/pulse/context.c
> @@ -241,9 +241,9 @@ static void context_free(pa_context *c) {
>  #endif
>  
>      if (c->record_streams)
> -        pa_hashmap_free(c->record_streams, NULL);
> +        pa_hashmap_free(c->record_streams, NULL, NULL);
>      if (c->playback_streams)
> -        pa_hashmap_free(c->playback_streams, NULL);
> +        pa_hashmap_free(c->playback_streams, NULL, NULL);
>  
>      if (c->mempool)
>          pa_mempool_free(c->mempool);
> diff --git a/src/pulse/proplist.c b/src/pulse/proplist.c
> index 6e91103..ca3a4f9 100644
> --- a/src/pulse/proplist.c
> +++ b/src/pulse/proplist.c
> @@ -70,7 +70,7 @@ pa_proplist* pa_proplist_new(void) {
>  void pa_proplist_free(pa_proplist* p) {
>      pa_assert(p);
>  
> -    pa_hashmap_free(MAKE_HASHMAP(p), (pa_free_cb_t) property_free);
> +    pa_hashmap_free(MAKE_HASHMAP(p), NULL, (pa_free_cb_t) property_free);
>  }
>  
>  /** Will accept only valid UTF-8 */
> @@ -351,7 +351,7 @@ int pa_proplist_unset(pa_proplist *p, const char *key) {
>      if (!pa_proplist_key_valid(key))
>          return -1;
>  
> -    if (!(prop = pa_hashmap_remove(MAKE_HASHMAP(p), key)))
> +    if (!(prop = pa_hashmap_remove(MAKE_HASHMAP(p), key, NULL)))
>          return -2;
>  
>      property_free(prop);
> @@ -654,7 +654,7 @@ int pa_proplist_contains(pa_proplist *p, const char *key) {
>  void pa_proplist_clear(pa_proplist *p) {
>      pa_assert(p);
>  
> -    pa_hashmap_remove_all(MAKE_HASHMAP(p), (pa_free_cb_t) property_free);
> +    pa_hashmap_remove_all(MAKE_HASHMAP(p), NULL, (pa_free_cb_t) property_free);
>  }
>  
>  pa_proplist* pa_proplist_copy(const pa_proplist *p) {
> diff --git a/src/pulse/stream.c b/src/pulse/stream.c
> index 746179b..1ee1934 100644
> --- a/src/pulse/stream.c
> +++ b/src/pulse/stream.c
> @@ -260,7 +260,8 @@ static void stream_unlink(pa_stream *s) {
>          pa_pdispatch_unregister_reply(s->context->pdispatch, s);
>  
>      if (s->channel_valid) {
> -        pa_hashmap_remove((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, PA_UINT32_TO_PTR(s->channel));
> +        pa_hashmap_remove((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams,
> +                          PA_UINT32_TO_PTR(s->channel), NULL);
>          s->channel = 0;
>          s->channel_valid = false;
>      }
> diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
> index c771cac..6ea1e8f 100644
> --- a/src/pulsecore/card.c
> +++ b/src/pulsecore/card.c
> @@ -128,10 +128,10 @@ void pa_card_new_data_done(pa_card_new_data *data) {
>      pa_proplist_free(data->proplist);
>  
>      if (data->profiles)
> -        pa_hashmap_free(data->profiles, (pa_free_cb_t) pa_card_profile_free);
> +        pa_hashmap_free(data->profiles, NULL, (pa_free_cb_t) pa_card_profile_free);
>  
>      if (data->ports)
> -        pa_hashmap_free(data->ports, (pa_free_cb_t) pa_device_port_unref);
> +        pa_hashmap_free(data->ports, NULL, (pa_free_cb_t) pa_device_port_unref);
>  
>      pa_xfree(data->name);
>      pa_xfree(data->active_profile);
> @@ -239,10 +239,10 @@ void pa_card_free(pa_card *c) {
>      pa_assert(pa_idxset_isempty(c->sources));
>      pa_idxset_free(c->sources, NULL);
>  
> -    pa_hashmap_free(c->ports, (pa_free_cb_t) pa_device_port_unref);
> +    pa_hashmap_free(c->ports, NULL, (pa_free_cb_t) pa_device_port_unref);
>  
>      if (c->profiles)
> -        pa_hashmap_free(c->profiles, (pa_free_cb_t) pa_card_profile_free);
> +        pa_hashmap_free(c->profiles, NULL, (pa_free_cb_t) pa_card_profile_free);
>  
>      pa_proplist_free(c->proplist);
>      pa_xfree(c->driver);
> diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
> index b198822..9fb17dd 100644
> --- a/src/pulsecore/core.c
> +++ b/src/pulsecore/core.c
> @@ -194,10 +194,10 @@ static void core_free(pa_object *o) {
>      pa_idxset_free(c->sink_inputs, NULL);
>  
>      pa_assert(pa_hashmap_isempty(c->namereg));
> -    pa_hashmap_free(c->namereg, NULL);
> +    pa_hashmap_free(c->namereg, NULL, NULL);
>  
>      pa_assert(pa_hashmap_isempty(c->shared));
> -    pa_hashmap_free(c->shared, NULL);
> +    pa_hashmap_free(c->shared, NULL, NULL);
>  
>      pa_subscription_free_all(c);
>  
> diff --git a/src/pulsecore/database-simple.c b/src/pulsecore/database-simple.c
> index 0d22e5b..27a1710 100644
> --- a/src/pulsecore/database-simple.c
> +++ b/src/pulsecore/database-simple.c
> @@ -265,7 +265,7 @@ void pa_database_close(pa_database *database) {
>      pa_database_sync(database);
>      pa_xfree(db->filename);
>      pa_xfree(db->tmp_filename);
> -    pa_hashmap_free(db->map, (pa_free_cb_t) free_entry);
> +    pa_hashmap_free(db->map, NULL, (pa_free_cb_t) free_entry);
>      pa_xfree(db);
>  }
>  
> @@ -306,7 +306,7 @@ int pa_database_set(pa_database *database, const pa_datum *key, const pa_datum*
>          /* entry with same key exists in hashmap */
>          entry *r;
>          if (overwrite) {
> -            r = pa_hashmap_remove(db->map, key);
> +            r = pa_hashmap_remove(db->map, key, NULL);
>              pa_hashmap_put(db->map, &e->key, e);
>          } else {
>              /* won't overwrite, so clean new entry */
> @@ -327,7 +327,7 @@ int pa_database_unset(pa_database *database, const pa_datum *key) {
>      pa_assert(db);
>      pa_assert(key);
>  
> -    e = pa_hashmap_remove(db->map, key);
> +    e = pa_hashmap_remove(db->map, key, NULL);
>      if (!e)
>          return -1;
>  
> @@ -337,11 +337,11 @@ int pa_database_unset(pa_database *database, const pa_datum *key) {
>  }
>  
>  int pa_database_clear(pa_database *database) {
> -    simple_data *db = (simple_data*)database;
> +    simple_data *db = (simple_data*) database;
>  
>      pa_assert(db);
>  
> -    pa_hashmap_remove_all(db->map, (pa_free_cb_t) free_entry);
> +    pa_hashmap_remove_all(db->map, NULL, (pa_free_cb_t) free_entry);
>  
>      return 0;
>  }
> diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c
> index 8bff5b6..46d617d 100644
> --- a/src/pulsecore/device-port.c
> +++ b/src/pulsecore/device-port.c
> @@ -98,7 +98,7 @@ static void device_port_free(pa_object *o) {
>          pa_proplist_free(p->proplist);
>  
>      if (p->profiles)
> -        pa_hashmap_free(p->profiles, NULL);
> +        pa_hashmap_free(p->profiles, NULL, NULL);
>  
>      pa_xfree(p->name);
>      pa_xfree(p->description);
> diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c
> index 0629164..6f3ae68 100644
> --- a/src/pulsecore/hashmap.c
> +++ b/src/pulsecore/hashmap.c
> @@ -35,7 +35,7 @@
>  #define NBUCKETS 127
>  
>  struct hashmap_entry {
> -    const void *key;
> +    void *key;
>      void *value;
>  
>      struct hashmap_entry *bucket_next, *bucket_previous;
> @@ -68,7 +68,7 @@ pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_f
>      return h;
>  }
>  
> -static void remove_entry(pa_hashmap *h, struct hashmap_entry *e) {
> +static void remove_entry(pa_hashmap *h, struct hashmap_entry *e, pa_free_cb_t key_free_cb) {
>      pa_assert(h);
>      pa_assert(e);
>  
> @@ -94,6 +94,9 @@ static void remove_entry(pa_hashmap *h, struct hashmap_entry *e) {
>          BY_HASH(h)[hash] = e->bucket_next;
>      }
>  
> +    if (key_free_cb)
> +        key_free_cb(e->key);
> +
>      if (pa_flist_push(PA_STATIC_FLIST_GET(entries), e) < 0)
>          pa_xfree(e);
>  
> @@ -101,10 +104,10 @@ static void remove_entry(pa_hashmap *h, struct hashmap_entry *e) {
>      h->n_entries--;
>  }
>  
> -void pa_hashmap_free(pa_hashmap *h, pa_free_cb_t free_cb) {
> +void pa_hashmap_free(pa_hashmap *h, pa_free_cb_t key_free_cb, pa_free_cb_t value_free_cb) {
>      pa_assert(h);
>  
> -    pa_hashmap_remove_all(h, free_cb);
> +    pa_hashmap_remove_all(h, key_free_cb, value_free_cb);
>      pa_xfree(h);
>  }
>  
> @@ -120,7 +123,7 @@ static struct hashmap_entry *hash_scan(pa_hashmap *h, unsigned hash, const void
>      return NULL;
>  }
>  
> -int pa_hashmap_put(pa_hashmap *h, const void *key, void *value) {
> +int pa_hashmap_put(pa_hashmap *h, void *key, void *value) {
>      struct hashmap_entry *e;
>      unsigned hash;
>  
> @@ -176,7 +179,7 @@ void* pa_hashmap_get(pa_hashmap *h, const void *key) {
>      return e->value;
>  }
>  
> -void* pa_hashmap_remove(pa_hashmap *h, const void *key) {
> +void* pa_hashmap_remove(pa_hashmap *h, const void *key, pa_free_cb_t key_free_cb) {
>      struct hashmap_entry *e;
>      unsigned hash;
>      void *data;
> @@ -189,21 +192,21 @@ void* pa_hashmap_remove(pa_hashmap *h, const void *key) {
>          return NULL;
>  
>      data = e->value;
> -    remove_entry(h, e);
> +    remove_entry(h, e, key_free_cb);
>  
>      return data;
>  }
>  
> -void pa_hashmap_remove_all(pa_hashmap *h, pa_free_cb_t free_cb) {
> +void pa_hashmap_remove_all(pa_hashmap *h, pa_free_cb_t key_free_cb, pa_free_cb_t value_free_cb) {
>      pa_assert(h);
>  
>      while (h->iterate_list_head) {
>          void *data;
>          data = h->iterate_list_head->value;
> -        remove_entry(h, h->iterate_list_head);
> +        remove_entry(h, h->iterate_list_head, key_free_cb);
>  
> -        if (free_cb)
> -            free_cb(data);
> +        if (value_free_cb)
> +            value_free_cb(data);
>      }
>  }
>  
> @@ -291,7 +294,7 @@ void* pa_hashmap_last(pa_hashmap *h) {
>      return h->iterate_list_tail->value;
>  }
>  
> -void* pa_hashmap_steal_first(pa_hashmap *h) {
> +void* pa_hashmap_steal_first(pa_hashmap *h, pa_free_cb_t key_free_cb) {
>      void *data;
>  
>      pa_assert(h);
> @@ -300,7 +303,7 @@ void* pa_hashmap_steal_first(pa_hashmap *h) {
>          return NULL;
>  
>      data = h->iterate_list_head->value;
> -    remove_entry(h, h->iterate_list_head);
> +    remove_entry(h, h->iterate_list_head, key_free_cb);
>  
>      return data;
>  }
> diff --git a/src/pulsecore/hashmap.h b/src/pulsecore/hashmap.h
> index a57fab3..7524099 100644
> --- a/src/pulsecore/hashmap.h
> +++ b/src/pulsecore/hashmap.h
> @@ -36,20 +36,20 @@ typedef struct pa_hashmap pa_hashmap;
>  /* Create a new hashmap. Use the specified functions for hashing and comparing objects in the map */
>  pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func);
>  
> -/* Free the hash table. Calls the specified function for every value in the table. The function may be NULL */
> -void pa_hashmap_free(pa_hashmap*, pa_free_cb_t free_cb);
> +/* Free the hash table. Calls the specified functions for every key and value in the table. The function may be NULL */
> +void pa_hashmap_free(pa_hashmap*, pa_free_cb_t key_free_cb, pa_free_cb_t value_free_cbfree_cb);
>  
>  /* Add an entry to the hashmap. Returns non-zero when the entry already exists */
> -int pa_hashmap_put(pa_hashmap *h, const void *key, void *value);
> +int pa_hashmap_put(pa_hashmap *h, void *key, void *value);
>  
>  /* Return an entry from the hashmap */
>  void* pa_hashmap_get(pa_hashmap *h, const void *key);
>  
>  /* Returns the data of the entry while removing */
> -void* pa_hashmap_remove(pa_hashmap *h, const void *key);
> +void* pa_hashmap_remove(pa_hashmap *h, const void *key, pa_free_cb_t key_free_cb);
>  
> -/* If free_cb is not NULL, it's called for each entry. */
> -void pa_hashmap_remove_all(pa_hashmap *h, pa_free_cb_t free_cb);
> +/* If the free_cbs are not NULL, they are called for each key and entry. */
> +void pa_hashmap_remove_all(pa_hashmap *h, pa_free_cb_t key_free_cb, pa_free_cb_t value_free_cb);
>  
>  /* Return the current number of entries of the hashmap */
>  unsigned pa_hashmap_size(pa_hashmap *h);
> @@ -69,7 +69,7 @@ void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void**key);
>  void *pa_hashmap_iterate_backwards(pa_hashmap *h, void **state, const void**key);
>  
>  /* Remove the oldest entry in the hashmap and return it */
> -void *pa_hashmap_steal_first(pa_hashmap *h);
> +void *pa_hashmap_steal_first(pa_hashmap *h, pa_free_cb_t key_free_cb);
>  
>  /* Return the oldest entry in the hashmap */
>  void* pa_hashmap_first(pa_hashmap *h);
> diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
> index 2d83b72..9ebc66c 100644
> --- a/src/pulsecore/memblock.c
> +++ b/src/pulsecore/memblock.c
> @@ -541,7 +541,7 @@ static void memblock_free(pa_memblock *b) {
>  
>              pa_mutex_lock(import->mutex);
>  
> -            pa_assert_se(pa_hashmap_remove(import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id)));
> +            pa_assert_se(pa_hashmap_remove(import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id), NULL));
>  
>              pa_assert(segment->n_blocks >= 1);
>              if (-- segment->n_blocks <= 0)
> @@ -701,7 +701,7 @@ static void memblock_replace_import(pa_memblock *b) {
>  
>      pa_mutex_lock(import->mutex);
>  
> -    pa_assert_se(pa_hashmap_remove(import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id)));
> +    pa_assert_se(pa_hashmap_remove(import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id), NULL));
>  
>      memblock_make_local(b);
>  
> @@ -929,7 +929,7 @@ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) {
>  static void segment_detach(pa_memimport_segment *seg) {
>      pa_assert(seg);
>  
> -    pa_hashmap_remove(seg->import->segments, PA_UINT32_TO_PTR(seg->memory.id));
> +    pa_hashmap_remove(seg->import->segments, PA_UINT32_TO_PTR(seg->memory.id), NULL);
>      pa_shm_free(&seg->memory);
>  
>      if (seg->trap)
> @@ -964,8 +964,8 @@ void pa_memimport_free(pa_memimport *i) {
>  
>      pa_mutex_unlock(i->pool->mutex);
>  
> -    pa_hashmap_free(i->blocks, NULL);
> -    pa_hashmap_free(i->segments, NULL);
> +    pa_hashmap_free(i->blocks, NULL, NULL);
> +    pa_hashmap_free(i->segments, NULL, NULL);
>  
>      pa_mutex_free(i->mutex);
>  
> diff --git a/src/pulsecore/modargs.c b/src/pulsecore/modargs.c
> index 09ca9fc..8d8964d 100644
> --- a/src/pulsecore/modargs.c
> +++ b/src/pulsecore/modargs.c
> @@ -259,8 +259,8 @@ static void free_func(void *p) {
>  void pa_modargs_free(pa_modargs*ma) {
>      pa_assert(ma);
>  
> -    pa_hashmap_free(ma->raw, free_func);
> -    pa_hashmap_free(ma->unescaped, free_func);
> +    pa_hashmap_free(ma->raw, NULL, free_func);
> +    pa_hashmap_free(ma->unescaped, NULL, free_func);
>      pa_xfree(ma);
>  }
>  
> diff --git a/src/pulsecore/mutex-win32.c b/src/pulsecore/mutex-win32.c
> index 01e8b4a..aa80fb0 100644
> --- a/src/pulsecore/mutex-win32.c
> +++ b/src/pulsecore/mutex-win32.c
> @@ -80,7 +80,7 @@ pa_cond *pa_cond_new(void) {
>  void pa_cond_free(pa_cond *c) {
>      assert(c);
>  
> -    pa_hashmap_free(c->wait_events, NULL);
> +    pa_hashmap_free(c->wait_events, NULL, NULL);
>      pa_xfree(c);
>  }
>  
> @@ -125,7 +125,7 @@ int pa_cond_wait(pa_cond *c, pa_mutex *m) {
>  
>      pa_mutex_lock(m);
>  
> -    pa_hashmap_remove(c->wait_events, event);
> +    pa_hashmap_remove(c->wait_events, event, NULL);
>  
>      CloseHandle(event);
>  
> diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c
> index 7704abe..a8a6ff6 100644
> --- a/src/pulsecore/namereg.c
> +++ b/src/pulsecore/namereg.c
> @@ -190,7 +190,7 @@ void pa_namereg_unregister(pa_core *c, const char *name) {
>      pa_assert(c);
>      pa_assert(name);
>  
> -    pa_assert_se(e = pa_hashmap_remove(c->namereg, name));
> +    pa_assert_se(e = pa_hashmap_remove(c->namereg, name, NULL));
>  
>      if (c->default_sink == e->data)
>          pa_namereg_set_default_sink(c, NULL);
> diff --git a/src/pulsecore/protocol-dbus.c b/src/pulsecore/protocol-dbus.c
> index 0ff4d83..02deee2 100644
> --- a/src/pulsecore/protocol-dbus.c
> +++ b/src/pulsecore/protocol-dbus.c
> @@ -169,8 +169,8 @@ void pa_dbus_protocol_unref(pa_dbus_protocol *p) {
>      pa_assert(pa_hashmap_isempty(p->connections));
>      pa_assert(pa_idxset_isempty(p->extensions));
>  
> -    pa_hashmap_free(p->objects, NULL);
> -    pa_hashmap_free(p->connections, NULL);
> +    pa_hashmap_free(p->objects, NULL, NULL);
> +    pa_hashmap_free(p->connections, NULL, NULL);
>      pa_idxset_free(p->extensions, NULL);
>  
>      for (i = 0; i < PA_DBUS_PROTOCOL_HOOK_MAX; ++i)
> @@ -649,7 +649,7 @@ static pa_hashmap *create_method_handlers(const pa_dbus_interface_info *info) {
>          h->n_arguments = info->method_handlers[i].n_arguments;
>          h->receive_cb = info->method_handlers[i].receive_cb;
>  
> -        pa_hashmap_put(handlers, h->method_name, h);
> +        pa_hashmap_put(handlers, (char *) h->method_name, h);
>      }
>  
>      return handlers;
> @@ -674,7 +674,7 @@ static pa_hashmap *extract_method_signatures(pa_hashmap *method_handlers) {
>                  pa_strbuf_puts(sig_buf, handler->arguments[i].type);
>          }
>  
> -        pa_hashmap_put(signatures, handler->method_name, pa_strbuf_tostring_free(sig_buf));
> +        pa_hashmap_put(signatures, (char *) handler->method_name, pa_strbuf_tostring_free(sig_buf));
>      }
>  
>      return signatures;
> @@ -696,7 +696,7 @@ static pa_hashmap *create_property_handlers(const pa_dbus_interface_info *info)
>          h->get_cb = info->property_handlers[i].get_cb;
>          h->set_cb = info->property_handlers[i].set_cb;
>  
> -        pa_hashmap_put(handlers, h->property_name, h);
> +        pa_hashmap_put(handlers, (char *) h->property_name, h);
>      }
>  
>      return handlers;
> @@ -827,7 +827,7 @@ int pa_dbus_protocol_remove_interface(pa_dbus_protocol *p, const char* path, con
>      if (!(obj_entry = pa_hashmap_get(p->objects, path)))
>          return -1;
>  
> -    if (!(iface_entry = pa_hashmap_remove(obj_entry->interfaces, interface)))
> +    if (!(iface_entry = pa_hashmap_remove(obj_entry->interfaces, interface, NULL)))
>          return -1;
>  
>      update_introspection(obj_entry);
> @@ -835,9 +835,9 @@ int pa_dbus_protocol_remove_interface(pa_dbus_protocol *p, const char* path, con
>      pa_log_debug("Interface %s removed from object %s", iface_entry->name, obj_entry->path);
>  
>      pa_xfree(iface_entry->name);
> -    pa_hashmap_free(iface_entry->method_signatures, pa_xfree);
> -    pa_hashmap_free(iface_entry->method_handlers, (pa_free_cb_t) method_handler_free);
> -    pa_hashmap_free(iface_entry->property_handlers, (pa_free_cb_t) property_handler_free);
> +    pa_hashmap_free(iface_entry->method_signatures, NULL, pa_xfree);
> +    pa_hashmap_free(iface_entry->method_handlers, NULL, (pa_free_cb_t) method_handler_free);
> +    pa_hashmap_free(iface_entry->property_handlers, NULL, (pa_free_cb_t) property_handler_free);
>  
>      for (i = 0; i < iface_entry->n_signals; ++i) {
>          unsigned j;
> @@ -859,9 +859,9 @@ int pa_dbus_protocol_remove_interface(pa_dbus_protocol *p, const char* path, con
>      if (pa_hashmap_isempty(obj_entry->interfaces)) {
>          unregister_object(p, obj_entry);
>  
> -        pa_hashmap_remove(p->objects, path);
> +        pa_hashmap_remove(p->objects, path, NULL);
>          pa_xfree(obj_entry->path);
> -        pa_hashmap_free(obj_entry->interfaces, NULL);
> +        pa_hashmap_free(obj_entry->interfaces, NULL, NULL);
>          pa_xfree(obj_entry->introspection);
>          pa_xfree(obj_entry);
>      }
> @@ -941,14 +941,14 @@ int pa_dbus_protocol_unregister_connection(pa_dbus_protocol *p, DBusConnection *
>      pa_assert(p);
>      pa_assert(conn);
>  
> -    if (!(conn_entry = pa_hashmap_remove(p->connections, conn)))
> +    if (!(conn_entry = pa_hashmap_remove(p->connections, conn, NULL)))
>          return -1;
>  
>      unregister_all_objects(p, conn);
>  
>      dbus_connection_unref(conn_entry->connection);
>      pa_idxset_free(conn_entry->all_signals_objects, pa_xfree);
> -    pa_hashmap_free(conn_entry->listening_signals, (pa_free_cb_t) signal_paths_entry_free);
> +    pa_hashmap_free(conn_entry->listening_signals, NULL, (pa_free_cb_t) signal_paths_entry_free);
>      pa_xfree(conn_entry);
>  
>      return 0;
> @@ -992,7 +992,7 @@ void pa_dbus_protocol_add_signal_listener(
>  
>          /* Replace the old signal paths entry for this signal with a new
>           * one. */
> -        if ((signal_paths_entry = pa_hashmap_remove(conn_entry->listening_signals, signal_name)))
> +        if ((signal_paths_entry = pa_hashmap_remove(conn_entry->listening_signals, signal_name, NULL)))
>              signal_paths_entry_free(signal_paths_entry);
>          signal_paths_entry = signal_paths_entry_new(signal_name);
>  
> @@ -1006,7 +1006,7 @@ void pa_dbus_protocol_add_signal_listener(
>  
>          /* We're not interested in individual signals anymore, so let's empty
>           * listening_signals. */
> -        pa_hashmap_remove_all(conn_entry->listening_signals, (pa_free_cb_t) signal_paths_entry_free);
> +        pa_hashmap_remove_all(conn_entry->listening_signals, NULL, (pa_free_cb_t) signal_paths_entry_free);
>  
>          for (i = 0; i < n_objects; ++i)
>              pa_idxset_put(conn_entry->all_signals_objects, pa_xstrdup(objects[i]), NULL);
> @@ -1023,13 +1023,13 @@ void pa_dbus_protocol_remove_signal_listener(pa_dbus_protocol *p, DBusConnection
>      pa_assert_se((conn_entry = pa_hashmap_get(p->connections, conn)));
>  
>      if (signal_name) {
> -        if ((signal_paths_entry = pa_hashmap_remove(conn_entry->listening_signals, signal_name)))
> +        if ((signal_paths_entry = pa_hashmap_remove(conn_entry->listening_signals, signal_name, NULL)))
>              signal_paths_entry_free(signal_paths_entry);
>  
>      } else {
>          conn_entry->listening_for_all_signals = false;
>          pa_idxset_remove_all(conn_entry->all_signals_objects, pa_xfree);
> -        pa_hashmap_remove_all(conn_entry->listening_signals, (pa_free_cb_t) signal_paths_entry_free);
> +        pa_hashmap_remove_all(conn_entry->listening_signals, NULL, (pa_free_cb_t) signal_paths_entry_free);
>      }
>  }
>  
> diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
> index 9342c1a..42f1e4d 100644
> --- a/src/pulsecore/protocol-native.c
> +++ b/src/pulsecore/protocol-native.c
> @@ -5139,7 +5139,7 @@ void pa_native_protocol_unref(pa_native_protocol *p) {
>      for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
>          pa_hook_done(&p->hooks[h]);
>  
> -    pa_hashmap_free(p->extensions, NULL);
> +    pa_hashmap_free(p->extensions, NULL, NULL);
>  
>      pa_assert_se(pa_shared_remove(p->core, "native-protocol") >= 0);
>  
> @@ -5196,7 +5196,7 @@ void pa_native_protocol_remove_ext(pa_native_protocol *p, pa_module *m) {
>      pa_assert(PA_REFCNT_VALUE(p) >= 1);
>      pa_assert(m);
>  
> -    pa_assert_se(pa_hashmap_remove(p->extensions, m));
> +    pa_assert_se(pa_hashmap_remove(p->extensions, m, NULL));
>  }
>  
>  pa_native_options* pa_native_options_new(void) {
> diff --git a/src/pulsecore/shared.c b/src/pulsecore/shared.c
> index 368a6c3..ea725d7 100644
> --- a/src/pulsecore/shared.c
> +++ b/src/pulsecore/shared.c
> @@ -91,7 +91,7 @@ int pa_shared_remove(pa_core *c, const char *name) {
>      pa_assert(name);
>      pa_assert(c->shared);
>  
> -    if (!(p = pa_hashmap_remove(c->shared, name)))
> +    if (!(p = pa_hashmap_remove(c->shared, name, NULL)))
>          return -1;
>  
>      shared_free(p);
> diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
> index 47f169e..87ddad4 100644
> --- a/src/pulsecore/sink-input.c
> +++ b/src/pulsecore/sink-input.c
> @@ -241,10 +241,10 @@ void pa_sink_input_new_data_done(pa_sink_input_new_data *data) {
>          pa_format_info_free(data->format);
>  
>      if (data->volume_factor_items)
> -        pa_hashmap_free(data->volume_factor_items, (pa_free_cb_t) volume_factor_entry_free);
> +        pa_hashmap_free(data->volume_factor_items, NULL, (pa_free_cb_t) volume_factor_entry_free);
>  
>      if (data->volume_factor_sink_items)
> -        pa_hashmap_free(data->volume_factor_sink_items, (pa_free_cb_t) volume_factor_entry_free);
> +        pa_hashmap_free(data->volume_factor_sink_items, NULL, (pa_free_cb_t) volume_factor_entry_free);
>  
>      pa_proplist_free(data->proplist);
>  }
> @@ -766,13 +766,13 @@ static void sink_input_free(pa_object *o) {
>          pa_idxset_free(i->direct_outputs, NULL);
>  
>      if (i->thread_info.direct_outputs)
> -        pa_hashmap_free(i->thread_info.direct_outputs, NULL);
> +        pa_hashmap_free(i->thread_info.direct_outputs, NULL, NULL);
>  
>      if (i->volume_factor_items)
> -        pa_hashmap_free(i->volume_factor_items, (pa_free_cb_t) volume_factor_entry_free);
> +        pa_hashmap_free(i->volume_factor_items, NULL, (pa_free_cb_t) volume_factor_entry_free);
>  
>      if (i->volume_factor_sink_items)
> -        pa_hashmap_free(i->volume_factor_sink_items, (pa_free_cb_t) volume_factor_entry_free);
> +        pa_hashmap_free(i->volume_factor_sink_items, NULL, (pa_free_cb_t) volume_factor_entry_free);
>  
>      pa_xfree(i->driver);
>      pa_xfree(i);
> @@ -1340,7 +1340,7 @@ int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key) {
>      pa_assert_ctl_context();
>      pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
>  
> -    v = pa_hashmap_remove(i->volume_factor_items, key);
> +    v = pa_hashmap_remove(i->volume_factor_items, key, NULL);
>  
>      if (!v)
>          return -1;
> diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
> index 3cdabd4..00bc29a 100644
> --- a/src/pulsecore/sink.c
> +++ b/src/pulsecore/sink.c
> @@ -142,7 +142,7 @@ void pa_sink_new_data_done(pa_sink_new_data *data) {
>      pa_proplist_free(data->proplist);
>  
>      if (data->ports)
> -        pa_hashmap_free(data->ports, (pa_free_cb_t) pa_device_port_unref);
> +        pa_hashmap_free(data->ports, NULL, (pa_free_cb_t) pa_device_port_unref);
>  
>      pa_xfree(data->name);
>      pa_xfree(data->active_port);
> @@ -730,7 +730,7 @@ static void sink_free(pa_object *o) {
>      }
>  
>      pa_idxset_free(s->inputs, NULL);
> -    pa_hashmap_free(s->thread_info.inputs, (pa_free_cb_t) pa_sink_input_unref);
> +    pa_hashmap_free(s->thread_info.inputs, NULL, (pa_free_cb_t) pa_sink_input_unref);
>  
>      if (s->silence.memblock)
>          pa_memblock_unref(s->silence.memblock);
> @@ -742,7 +742,7 @@ static void sink_free(pa_object *o) {
>          pa_proplist_free(s->proplist);
>  
>      if (s->ports)
> -        pa_hashmap_free(s->ports, (pa_free_cb_t) pa_device_port_unref);
> +        pa_hashmap_free(s->ports, NULL, (pa_free_cb_t) pa_device_port_unref);
>  
>      pa_xfree(s);
>  }
> @@ -2543,7 +2543,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
>                  i->thread_info.sync_next = NULL;
>              }
>  
> -            if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
> +            if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), NULL))
>                  pa_sink_input_unref(i);
>  
>              pa_sink_invalidate_requested_latency(s, true);
> @@ -2626,7 +2626,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
>              i->thread_info.attached = false;
>  
>              /* Let's remove the sink input ...*/
> -            if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
> +            if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), NULL))
>                  pa_sink_input_unref(i);
>  
>              pa_sink_invalidate_requested_latency(s, true);
> diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
> index 9c492c1..b14b9c8 100644
> --- a/src/pulsecore/source.c
> +++ b/src/pulsecore/source.c
> @@ -133,7 +133,7 @@ void pa_source_new_data_done(pa_source_new_data *data) {
>      pa_proplist_free(data->proplist);
>  
>      if (data->ports)
> -        pa_hashmap_free(data->ports, (pa_free_cb_t) pa_device_port_unref);
> +        pa_hashmap_free(data->ports, NULL, (pa_free_cb_t) pa_device_port_unref);
>  
>      pa_xfree(data->name);
>      pa_xfree(data->active_port);
> @@ -660,7 +660,7 @@ static void source_free(pa_object *o) {
>      pa_log_info("Freeing source %u \"%s\"", s->index, s->name);
>  
>      pa_idxset_free(s->outputs, NULL);
> -    pa_hashmap_free(s->thread_info.outputs, (pa_free_cb_t) pa_source_output_unref);
> +    pa_hashmap_free(s->thread_info.outputs, NULL, (pa_free_cb_t) pa_source_output_unref);
>  
>      if (s->silence.memblock)
>          pa_memblock_unref(s->silence.memblock);
> @@ -672,7 +672,7 @@ static void source_free(pa_object *o) {
>          pa_proplist_free(s->proplist);
>  
>      if (s->ports)
> -        pa_hashmap_free(s->ports, (pa_free_cb_t) pa_device_port_unref);
> +        pa_hashmap_free(s->ports, NULL, (pa_free_cb_t) pa_device_port_unref);
>  
>      pa_xfree(s);
>  }
> @@ -2024,11 +2024,11 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
>              o->thread_info.attached = false;
>  
>              if (o->thread_info.direct_on_input) {
> -                pa_hashmap_remove(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index));
> +                pa_hashmap_remove(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index), NULL);
>                  o->thread_info.direct_on_input = NULL;
>              }
>  
> -            if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index)))
> +            if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), NULL))
>                  pa_source_output_unref(o);
>  
>              pa_source_invalidate_requested_latency(s, true);
> 



-- 
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic


More information about the pulseaudio-discuss mailing list