[Spice-devel] [PATCH spice-gtk 08/10] gtk: use GHashTable in display_cache
Yonit Halperin
yhalperi at redhat.com
Mon Sep 9 12:19:20 PDT 2013
Hi,
In general it looks good, but I have several comments:
(1) the palette cache shouldn't be shared among the display channels.
I.e., there should be one instance per channel, and not one instance in
spice-session.
(2) I think you changed the ref_count logic of cache item. Now each
cache value is referenced by the cache only once.
While multiple insertions and deletions from the cache shouldn't occur,
I believe that the previous ref counting may be the reason that even
though the palette cache was shared by the channels (while it shouldn't
have been), deleting palettes with ref_count > 1, didn't cause errors.
(3) hash function: the unique id can serve as the hash key, so you can
just use the identity function instead of g_int64_hash
Best,
Yonit.
On 09/08/2013 02:59 PM, Marc-André Lureau wrote:
> From: Marc-André Lureau <marcandre.lureau at gmail.com>
>
> The cache code isn't very quick, it shows up in profilers. Using
> GHashTable allows to simplify the code while making it faster.
> ---
> gtk/channel-cursor.c | 56 +++++++----------------
> gtk/channel-display.c | 93 +++++++++++---------------------------
> gtk/spice-channel-cache.h | 111 +++++++++++++++++-----------------------------
> gtk/spice-session-priv.h | 4 +-
> gtk/spice-session.c | 58 +++++++-----------------
> spice-common | 2 +-
> 6 files changed, 103 insertions(+), 221 deletions(-)
>
> diff --git a/gtk/channel-cursor.c b/gtk/channel-cursor.c
> index e4a996b..eb53843 100644
> --- a/gtk/channel-cursor.c
> +++ b/gtk/channel-cursor.c
> @@ -51,7 +51,7 @@ struct display_cursor {
> };
>
> struct _SpiceCursorChannelPrivate {
> - display_cache cursors;
> + display_cache *cursors;
> gboolean init_done;
> };
>
> @@ -67,7 +67,6 @@ enum {
> static guint signals[SPICE_CURSOR_LAST_SIGNAL];
>
> static void spice_cursor_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg);
> -static void delete_cursor_all(SpiceChannel *channel);
> static display_cursor * display_cursor_ref(display_cursor *cursor);
> static void display_cursor_unref(display_cursor *cursor);
>
> @@ -81,12 +80,14 @@ static void spice_cursor_channel_init(SpiceCursorChannel *channel)
>
> c = channel->priv = SPICE_CURSOR_CHANNEL_GET_PRIVATE(channel);
>
> - cache_init(&c->cursors, "cursor");
> + c->cursors = cache_new((GDestroyNotify)display_cursor_unref);
> }
>
> static void spice_cursor_channel_finalize(GObject *obj)
> {
> - delete_cursor_all(SPICE_CHANNEL(obj));
> + SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL_GET_PRIVATE(obj);
> +
> + g_clear_pointer(&c->cursors, cache_unref);
>
> if (G_OBJECT_CLASS(spice_cursor_channel_parent_class)->finalize)
> G_OBJECT_CLASS(spice_cursor_channel_parent_class)->finalize(obj);
> @@ -97,7 +98,7 @@ static void spice_cursor_channel_reset(SpiceChannel *channel, gboolean migrating
> {
> SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
>
> - delete_cursor_all(channel);
> + cache_clear(c->cursors);
> c->init_done = FALSE;
>
> SPICE_CHANNEL_CLASS(spice_cursor_channel_parent_class)->channel_reset(channel, migrating);
> @@ -359,7 +360,6 @@ static display_cursor *set_cursor(SpiceChannel *channel, SpiceCursor *scursor)
> {
> SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
> SpiceCursorHeader *hdr = &scursor->header;
> - display_cache_item *item;
> display_cursor *cursor;
> size_t size;
> gint i, pix_mask, pix;
> @@ -378,9 +378,9 @@ static display_cursor *set_cursor(SpiceChannel *channel, SpiceCursor *scursor)
> hdr->width, hdr->height);
>
> if (scursor->flags & SPICE_CURSOR_FLAGS_FROM_CACHE) {
> - item = cache_find(&c->cursors, hdr->unique);
> - g_return_val_if_fail(item != NULL, NULL);
> - return display_cursor_ref(item->ptr);
> + cursor = cache_find(c->cursors, hdr->unique);
> + g_return_val_if_fail(cursor != NULL, NULL);
> + return display_cursor_ref(cursor);
> }
>
> g_return_val_if_fail(scursor->data_size != 0, NULL);
> @@ -453,36 +453,12 @@ static display_cursor *set_cursor(SpiceChannel *channel, SpiceCursor *scursor)
>
> cache_add:
> if (cursor && (scursor->flags & SPICE_CURSOR_FLAGS_CACHE_ME)) {
> - display_cursor_ref(cursor);
> - item = cache_add(&c->cursors, hdr->unique);
> - item->ptr = cursor;
> + cache_add(c->cursors, hdr->unique, display_cursor_ref(cursor));
> }
>
> return cursor;
> }
>
> -static void delete_cursor_one(SpiceChannel *channel, display_cache_item *item)
> -{
> - SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
> -
> - display_cursor_unref((display_cursor*)item->ptr);
> - cache_del(&c->cursors, item);
> -}
> -
> -static void delete_cursor_all(SpiceChannel *channel)
> -{
> - SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
> - display_cache_item *item;
> -
> - for (;;) {
> - item = cache_get_lru(&c->cursors);
> - if (item == NULL) {
> - return;
> - }
> - delete_cursor_one(channel, item);
> - }
> -}
> -
> /* coroutine context */
> static void emit_cursor_set(SpiceChannel *channel, display_cursor *cursor)
> {
> @@ -502,7 +478,7 @@ static void cursor_handle_init(SpiceChannel *channel, SpiceMsgIn *in)
>
> g_return_if_fail(c->init_done == FALSE);
>
> - delete_cursor_all(channel);
> + cache_clear(c->cursors);
> cursor = set_cursor(channel, &init->cursor);
> c->init_done = TRUE;
> if (cursor)
> @@ -520,7 +496,7 @@ static void cursor_handle_reset(SpiceChannel *channel, SpiceMsgIn *in)
>
> CHANNEL_DEBUG(channel, "%s, init_done: %d", __FUNCTION__, c->init_done);
>
> - delete_cursor_all(channel);
> + cache_clear(c->cursors);
> emit_main_context(channel, SPICE_CURSOR_RESET);
> c->init_done = FALSE;
> }
> @@ -584,18 +560,18 @@ static void cursor_handle_inval_one(SpiceChannel *channel, SpiceMsgIn *in)
> {
> SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
> SpiceMsgDisplayInvalOne *zap = spice_msg_in_parsed(in);
> - display_cache_item *item;
>
> g_return_if_fail(c->init_done == TRUE);
>
> - item = cache_find(&c->cursors, zap->id);
> - delete_cursor_one(channel, item);
> + cache_remove(c->cursors, zap->id);
> }
>
> /* coroutine context */
> static void cursor_handle_inval_all(SpiceChannel *channel, SpiceMsgIn *in)
> {
> - delete_cursor_all(channel);
> + SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
> +
> + cache_clear(c->cursors);
> }
>
> static const spice_msg_handler cursor_handlers[] = {
> diff --git a/gtk/channel-display.c b/gtk/channel-display.c
> index 03ae535..a69f14f 100644
> --- a/gtk/channel-display.c
> +++ b/gtk/channel-display.c
> @@ -486,16 +486,8 @@ static void image_put(SpiceImageCache *cache, uint64_t id, pixman_image_t *image
> {
> SpiceDisplayChannelPrivate *c =
> SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, image_cache);
> - display_cache_item *item;
>
> - item = cache_find(c->images, id);
> - if (item) {
> - cache_ref(item);
> - return;
> - }
> -
> - item = cache_add(c->images, id);
> - item->ptr = pixman_image_ref(image);
> + cache_add(c->images, id, pixman_image_ref(image));
> }
>
> typedef struct _WaitImageData
> @@ -508,18 +500,16 @@ typedef struct _WaitImageData
>
> static gboolean wait_image(gpointer data)
> {
> - display_cache_item *item;
> + gboolean lossy;
> WaitImageData *wait = data;
> SpiceDisplayChannelPrivate *c =
> SPICE_CONTAINEROF(wait->cache, SpiceDisplayChannelPrivate, image_cache);
> + pixman_image_t *image = cache_find_lossy(c->images, wait->id, &lossy);
>
> - item = cache_find(c->images, wait->id);
> - if (item == NULL ||
> - (item->lossy && !wait->lossy))
> + if (!image || (lossy && !wait->lossy))
> return FALSE;
>
> - cache_used(c->images, item);
> - wait->image = pixman_image_ref(item->ptr);
> + wait->image = pixman_image_ref(image);
>
> return TRUE;
> }
> @@ -538,58 +528,33 @@ static pixman_image_t *image_get(SpiceImageCache *cache, uint64_t id)
> return wait.image;
> }
>
> -static void image_remove(SpiceImageCache *cache, uint64_t id)
> -{
> - SpiceDisplayChannelPrivate *c =
> - SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, image_cache);
> - display_cache_item *item;
> -
> - item = cache_find(c->images, id);
> - g_return_if_fail(item != NULL);
> - if (cache_unref(item)) {
> - pixman_image_unref(item->ptr);
> - cache_del(c->images, item);
> - }
> -}
> -
> static void palette_put(SpicePaletteCache *cache, SpicePalette *palette)
> {
> SpiceDisplayChannelPrivate *c =
> SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, palette_cache);
> - display_cache_item *item;
>
> - item = cache_add(c->palettes, palette->unique);
> - item->ptr = g_memdup(palette, sizeof(SpicePalette) +
> - palette->num_ents * sizeof(palette->ents[0]));
> + cache_add(c->palettes, palette->unique,
> + g_memdup(palette, sizeof(SpicePalette) +
> + palette->num_ents * sizeof(palette->ents[0])));
> }
>
> static SpicePalette *palette_get(SpicePaletteCache *cache, uint64_t id)
> {
> SpiceDisplayChannelPrivate *c =
> SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, palette_cache);
> - display_cache_item *item;
>
> - item = cache_find(c->palettes, id);
> - if (item) {
> - cache_ref(item);
> - return item->ptr;
> - }
> - return NULL;
> + /* here the returned pointer is weak, no ref given to caller. it
> + * seems spice canvas usage is exclusively temporary, so it's ok
> + * (for now) */
> + return cache_find(c->palettes, id);
> }
>
> static void palette_remove(SpicePaletteCache *cache, uint32_t id)
> {
> SpiceDisplayChannelPrivate *c =
> SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, palette_cache);
> - display_cache_item *item;
>
> - item = cache_find(c->palettes, id);
> - if (item) {
> - if (cache_unref(item)) {
> - g_free(item->ptr);
> - cache_del(c->palettes, item);
> - }
> - }
> + cache_remove(c->palettes, id);
> }
>
> static void palette_release(SpicePaletteCache *cache, SpicePalette *palette)
> @@ -603,30 +568,18 @@ static void image_put_lossy(SpiceImageCache *cache, uint64_t id,
> {
> SpiceDisplayChannelPrivate *c =
> SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, image_cache);
> - display_cache_item *item;
>
> #ifndef NDEBUG
> g_warn_if_fail(cache_find(c->images, id) == NULL);
> #endif
>
> - item = cache_add(c->images, id);
> - item->ptr = pixman_image_ref(surface);
> - item->lossy = TRUE;
> + cache_add_lossy(c->images, id, pixman_image_ref(surface), TRUE);
> }
>
> static void image_replace_lossy(SpiceImageCache *cache, uint64_t id,
> pixman_image_t *surface)
> {
> - SpiceDisplayChannelPrivate *c =
> - SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, image_cache);
> - display_cache_item *item;
> -
> - item = cache_find(c->images, id);
> - g_return_if_fail(item != NULL);
> -
> - pixman_image_unref(item->ptr);
> - item->ptr = pixman_image_ref(surface);
> - item->lossy = FALSE;
> + image_put(cache, id, surface);
> }
>
> static pixman_image_t* image_get_lossless(SpiceImageCache *cache, uint64_t id)
> @@ -968,7 +921,7 @@ static void display_handle_reset(SpiceChannel *channel, SpiceMsgIn *in)
> if (surface != NULL)
> surface->canvas->ops->clear(surface->canvas);
>
> - spice_session_palettes_clear(spice_channel_get_session(channel));
> + cache_clear(c->palettes);
>
> c->mark = FALSE;
> emit_main_context(channel, SPICE_DISPLAY_MARK, FALSE);
> @@ -997,9 +950,12 @@ static void display_handle_inv_list(SpiceChannel *channel, SpiceMsgIn *in)
> int i;
>
> for (i = 0; i < list->count; i++) {
> + guint64 id = list->resources[i].id;
> +
> switch (list->resources[i].type) {
> case SPICE_RES_TYPE_PIXMAP:
> - image_remove(&c->image_cache, list->resources[i].id);
> + if (!cache_remove(c->images, id))
> + SPICE_DEBUG("fail to remove image %" G_GUINT64_FORMAT, id);
> break;
> default:
> g_return_if_reached();
> @@ -1011,9 +967,10 @@ static void display_handle_inv_list(SpiceChannel *channel, SpiceMsgIn *in)
> /* coroutine context */
> static void display_handle_inv_pixmap_all(SpiceChannel *channel, SpiceMsgIn *in)
> {
> - spice_channel_handle_wait_for_channels(channel, in);
> + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
>
> - spice_session_images_clear(spice_channel_get_session(channel));
> + spice_channel_handle_wait_for_channels(channel, in);
> + cache_clear(c->images);
> }
>
> /* coroutine context */
> @@ -1028,7 +985,9 @@ static void display_handle_inv_palette(SpiceChannel *channel, SpiceMsgIn *in)
> /* coroutine context */
> static void display_handle_inv_palette_all(SpiceChannel *channel, SpiceMsgIn *in)
> {
> - spice_session_palettes_clear(spice_channel_get_session(channel));
> + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> +
> + cache_clear(c->palettes);
> }
>
> /* ------------------------------------------------------------------ */
> diff --git a/gtk/spice-channel-cache.h b/gtk/spice-channel-cache.h
> index 3f39877..17775e6 100644
> --- a/gtk/spice-channel-cache.h
> +++ b/gtk/spice-channel-cache.h
> @@ -25,109 +25,80 @@
> G_BEGIN_DECLS
>
> typedef struct display_cache_item {
> - RingItem hash_link;
> - RingItem lru_link;
> - uint64_t id;
> - uint32_t refcount;
> - void *ptr;
> + guint64 id;
> gboolean lossy;
> } display_cache_item;
>
> -typedef struct display_cache {
> - const char *name;
> - Ring hash[64];
> - Ring lru;
> - int nitems;
> -} display_cache;
> +typedef GHashTable display_cache;
>
> -static inline void cache_init(display_cache *cache, const char *name)
> +static inline display_cache_item* cache_item_new(guint64 id, gboolean lossy)
> {
> - int i;
> + display_cache_item *self = g_slice_new(display_cache_item);
> + self->id = id;
> + self->lossy = lossy;
> + return self;
> +}
>
> - cache->name = name;
> - ring_init(&cache->lru);
> - for (i = 0; i < SPICE_N_ELEMENTS(cache->hash); i++) {
> - ring_init(&cache->hash[i]);
> - }
> +static inline void cache_item_free(display_cache_item *self)
> +{
> + g_slice_free(display_cache_item, self);
> }
>
> -static inline Ring *cache_head(display_cache *cache, uint64_t id)
> +static inline display_cache* cache_new(GDestroyNotify value_destroy)
> {
> - return &cache->hash[id % SPICE_N_ELEMENTS(cache->hash)];
> + GHashTable* self;
> +
> + self = g_hash_table_new_full(g_int64_hash, g_int64_equal,
> + (GDestroyNotify)cache_item_free,
> + value_destroy);
> +
> + return self;
> }
>
> -static inline void cache_used(display_cache *cache, display_cache_item *item)
> +static inline gpointer cache_find(display_cache *cache, uint64_t id)
> {
> - ring_remove(&item->lru_link);
> - ring_add(&cache->lru, &item->lru_link);
> + return g_hash_table_lookup(cache, &id);
> }
>
> -static inline display_cache_item *cache_get_lru(display_cache *cache)
> +static inline gpointer cache_find_lossy(display_cache *cache, uint64_t id, gboolean *lossy)
> {
> + gpointer value;
> display_cache_item *item;
> - RingItem *ring;
>
> - if (ring_is_empty(&cache->lru))
> + if (!g_hash_table_lookup_extended(cache, &id, (gpointer*)&item, &value))
> return NULL;
> - ring = ring_get_tail(&cache->lru);
> - item = SPICE_CONTAINEROF(ring, display_cache_item, lru_link);
> - return item;
> -}
>
> -static inline display_cache_item *cache_find(display_cache *cache, uint64_t id)
> -{
> - display_cache_item *item;
> - RingItem *ring;
> - Ring *head;
> -
> - head = cache_head(cache, id);
> - for (ring = ring_get_head(head); ring != NULL; ring = ring_next(head, ring)) {
> - item = SPICE_CONTAINEROF(ring, display_cache_item, hash_link);
> - if (item->id == id) {
> - return item;
> - }
> - }
> -
> - SPICE_DEBUG("%s: %s %" PRIx64 " [not found]", __FUNCTION__,
> - cache->name, id);
> - return NULL;
> + *lossy = item->lossy;
> +
> + return value;
> }
>
> -static inline display_cache_item *cache_add(display_cache *cache, uint64_t id)
> +static inline void cache_add_lossy(display_cache *cache, uint64_t id,
> + gpointer value, gboolean lossy)
> {
> - display_cache_item *item;
> + display_cache_item *item = cache_item_new(id, lossy);
>
> - item = spice_new0(display_cache_item, 1);
> - item->id = id;
> - item->refcount = 1;
> - ring_add(cache_head(cache, item->id), &item->hash_link);
> - ring_add(&cache->lru, &item->lru_link);
> - cache->nitems++;
> + g_hash_table_replace(cache, item, value);
> +}
>
> - SPICE_DEBUG("%s: %s %" PRIx64 " (%d)", __FUNCTION__,
> - cache->name, id, cache->nitems);
> - return item;
> +static inline void cache_add(display_cache *cache, uint64_t id, gpointer value)
> +{
> + cache_add_lossy(cache, id, value, FALSE);
> }
>
> -static inline void cache_del(display_cache *cache, display_cache_item *item)
> +static inline gboolean cache_remove(display_cache *cache, uint64_t id)
> {
> - SPICE_DEBUG("%s: %s %" PRIx64, __FUNCTION__,
> - cache->name, item->id);
> - ring_remove(&item->hash_link);
> - ring_remove(&item->lru_link);
> - free(item);
> - cache->nitems--;
> + return g_hash_table_remove(cache, &id);
> }
>
> -static inline void cache_ref(display_cache_item *item)
> +static inline void cache_clear(display_cache *cache)
> {
> - item->refcount++;
> + g_hash_table_remove_all(cache);
> }
>
> -static inline int cache_unref(display_cache_item *item)
> +static inline void cache_unref(display_cache *cache)
> {
> - item->refcount--;
> - return item->refcount == 0;
> + g_hash_table_unref(cache);
> }
>
> G_END_DECLS
> diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h
> index 5ed48dd..e175281 100644
> --- a/gtk/spice-session-priv.h
> +++ b/gtk/spice-session-priv.h
> @@ -92,8 +92,8 @@ struct _SpiceSessionPrivate {
> guint after_main_init;
> gboolean migration_copy;
>
> - display_cache images;
> - display_cache palettes;
> + display_cache *images;
> + display_cache *palettes;
> SpiceGlzDecoderWindow *glz_window;
> int images_cache_size;
> int glz_window_size;
> diff --git a/gtk/spice-session.c b/gtk/spice-session.c
> index a9435f4..c050266 100644
> --- a/gtk/spice-session.c
> +++ b/gtk/spice-session.c
> @@ -176,8 +176,8 @@ static void spice_session_init(SpiceSession *session)
> g_free(channels);
>
> ring_init(&s->channels);
> - cache_init(&s->images, "image");
> - cache_init(&s->palettes, "palette");
> + s->images = cache_new((GDestroyNotify)pixman_image_unref);
> + s->palettes = cache_new(g_free);
> s->glz_window = glz_decoder_window_new();
> update_proxy(session, NULL);
> }
> @@ -219,35 +219,6 @@ spice_session_dispose(GObject *gobject)
> G_OBJECT_CLASS(spice_session_parent_class)->dispose(gobject);
> }
>
> -G_GNUC_INTERNAL
> -void spice_session_palettes_clear(SpiceSession *session)
> -{
> - SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session);
> - g_return_if_fail(s != NULL);
> -
> - for (;;) {
> - display_cache_item *item = cache_get_lru(&s->palettes);
> - if (item == NULL)
> - break;
> - cache_del(&s->palettes, item);
> - }
> -}
> -
> -G_GNUC_INTERNAL
> -void spice_session_images_clear(SpiceSession *session)
> -{
> - SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session);
> - g_return_if_fail(s != NULL);
> -
> - for (;;) {
> - display_cache_item *item = cache_get_lru(&s->images);
> - if (item == NULL)
> - break;
> - pixman_image_unref(item->ptr);
> - cache_del(&s->images, item);
> - }
> -}
> -
> static void
> spice_session_finalize(GObject *gobject)
> {
> @@ -267,8 +238,8 @@ spice_session_finalize(GObject *gobject)
> g_strfreev(s->disable_effects);
> g_strfreev(s->secure_channels);
>
> - spice_session_palettes_clear(session);
> - spice_session_images_clear(session);
> + g_clear_pointer(&s->images, cache_unref);
> + g_clear_pointer(&s->palettes, cache_unref);
> glz_decoder_window_destroy(s->glz_window);
>
> g_clear_pointer(&s->pubkey, g_byte_array_unref);
> @@ -1332,6 +1303,15 @@ gboolean spice_session_get_client_provided_socket(SpiceSession *session)
> return s->client_provided_sockets;
> }
>
> +static void cache_clear_all(SpiceSession *self)
> +{
> + SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(self);
> +
> + cache_clear(s->images);
> + cache_clear(s->palettes);
> + glz_decoder_window_clear(s->glz_window);
> +}
> +
> G_GNUC_INTERNAL
> void spice_session_switching_disconnect(SpiceSession *self)
> {
> @@ -1353,9 +1333,7 @@ void spice_session_switching_disconnect(SpiceSession *self)
>
> g_warn_if_fail(!ring_is_empty(&s->channels)); /* ring_get_length() == 1 */
>
> - spice_session_palettes_clear(self);
> - spice_session_images_clear(self);
> - glz_decoder_window_clear(s->glz_window);
> + cache_clear_all(self);
> }
>
> G_GNUC_INTERNAL
> @@ -1561,9 +1539,7 @@ void spice_session_migrate_end(SpiceSession *self)
> }
> }
>
> - spice_session_palettes_clear(self);
> - spice_session_images_clear(self);
> - glz_decoder_window_clear(s->glz_window);
> + cache_clear_all(self);
>
> /* send MIGRATE_END to target */
> out = spice_msg_out_new(s->cmain, SPICE_MSGC_MAIN_MIGRATE_END);
> @@ -2119,9 +2095,9 @@ void spice_session_get_caches(SpiceSession *session,
> g_return_if_fail(s != NULL);
>
> if (images)
> - *images = &s->images;
> + *images = s->images;
> if (palettes)
> - *palettes = &s->palettes;
> + *palettes = s->palettes;
> if (glz_window)
> *glz_window = s->glz_window;
> }
> diff --git a/spice-common b/spice-common
> index fc27fb2..7aef065 160000
> --- a/spice-common
> +++ b/spice-common
> @@ -1 +1 @@
> -Subproject commit fc27fb20b8ecd3e07809aec884f99f2121712bc9
> +Subproject commit 7aef06577e47965bbe93e0a054857a562d2fde5a
>
More information about the Spice-devel
mailing list