Commit 737527e9 authored by Jiří Techet's avatar Jiří Techet

Rethink the tile destruction process once again

Instead of weak pointers ref and unref the tiles.
Signed-off-by: 's avatarJiří Techet <techet@gmail.com>
parent 3c391566
......@@ -526,14 +526,8 @@ tile_rendered_cb (ChamplainTile *tile,
GTimeVal modified_time = { 0, };
gchar *filename = NULL;
// this frees user_data
g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, user_data);
if (!map_source)
{
DEBUG ("Map source destroyed while loading");
return;
}
g_slice_free (FileLoadedData, user_data);
next_source = champlain_map_source_get_next_source (map_source);
file_cache = CHAMPLAIN_FILE_CACHE (map_source);
......@@ -624,20 +618,8 @@ load_next:
cleanup:
g_free (filename);
}
static void
destroy_cb_data (FileLoadedData *data,
G_GNUC_UNUSED GClosure *closure)
{
if (data->map_source)
g_object_remove_weak_pointer (G_OBJECT (data->map_source), (gpointer *) &data->map_source);
if (data->tile)
g_object_remove_weak_pointer (G_OBJECT (data->tile), (gpointer *) &data->tile);
g_slice_free (FileLoadedData, data);
g_object_unref (tile);
g_object_unref (map_source);
}
......@@ -666,24 +648,11 @@ file_loaded_cb (GFile *file,
g_object_unref (file);
if (!tile || !map_source)
{
if (map_source)
g_object_remove_weak_pointer (G_OBJECT (map_source), (gpointer *) &user_data->map_source);
if (tile)
g_object_remove_weak_pointer (G_OBJECT (tile), (gpointer *) &user_data->tile);
g_slice_free (FileLoadedData, user_data);
return;
}
renderer = champlain_map_source_get_renderer (map_source);
g_return_if_fail (CHAMPLAIN_IS_RENDERER (renderer));
g_signal_connect_data (tile, "render-complete", G_CALLBACK (tile_rendered_cb),
user_data, (GClosureNotify) destroy_cb_data, 0);
g_signal_connect (tile, "render-complete", G_CALLBACK (tile_rendered_cb), user_data);
champlain_renderer_set_data (renderer, contents, length);
g_free (contents);
......@@ -712,9 +681,9 @@ fill_tile (ChamplainMapSource *map_source,
user_data = g_slice_new (FileLoadedData);
user_data->tile = tile;
user_data->map_source = map_source;
g_object_add_weak_pointer (G_OBJECT (tile), (gpointer *) &user_data->tile);
g_object_add_weak_pointer (G_OBJECT (map_source), (gpointer *) &user_data->map_source);
g_object_ref (tile);
g_object_ref (map_source);
DEBUG ("fill of %s", filename);
......
......@@ -141,28 +141,17 @@ champlain_file_tile_source_load_map_data (ChamplainFileTileSource *self,
}
typedef struct
{
ChamplainMapSource *map_source;
} TileRenderedData;
static void
tile_rendered_cb (ChamplainTile *tile,
ChamplainRenderCallbackData *data,
TileRenderedData *user_data)
ChamplainMapSource *map_source)
{
ChamplainMapSource *map_source = user_data->map_source;
ChamplainMapSource *next_source;
// frees user_data - must not be used later in the function
g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, map_source);
if (!map_source)
return;
next_source = champlain_map_source_get_next_source (map_source);
if (!data->error)
{
ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE (map_source);
......@@ -177,17 +166,9 @@ tile_rendered_cb (ChamplainTile *tile,
}
else if (next_source)
champlain_map_source_fill_tile (next_source, tile);
}
static void
destroy_cb_data (TileRenderedData *data,
G_GNUC_UNUSED GClosure *closure)
{
if (data->map_source)
g_object_remove_weak_pointer (G_OBJECT (data->map_source), (gpointer *) &data->map_source);
g_slice_free (TileRenderedData, data);
g_object_unref (map_source);
g_object_unref (tile);
}
......@@ -203,19 +184,15 @@ fill_tile (ChamplainMapSource *map_source,
if (champlain_tile_get_state (tile) != CHAMPLAIN_STATE_LOADED)
{
ChamplainRenderer *renderer;
TileRenderedData *user_data;
renderer = champlain_map_source_get_renderer (map_source);
g_return_if_fail (CHAMPLAIN_IS_RENDERER (renderer));
user_data = g_slice_new (TileRenderedData);
user_data->map_source = map_source;
g_object_add_weak_pointer (G_OBJECT (map_source), (gpointer *) &user_data->map_source);
g_object_ref (map_source);
g_object_ref (tile);
g_signal_connect_data (tile, "render-complete", G_CALLBACK (tile_rendered_cb),
user_data, (GClosureNotify) destroy_cb_data, 0);
g_signal_connect (tile, "render-complete", G_CALLBACK (tile_rendered_cb), map_source);
champlain_renderer_render (renderer, tile);
}
......
......@@ -254,26 +254,15 @@ delete_queue_member (QueueMember *member, gpointer user_data)
}
typedef struct
{
ChamplainMapSource *map_source;
} TileRenderedData;
static void
tile_rendered_cb (ChamplainTile *tile,
ChamplainRenderCallbackData *data,
TileRenderedData *user_data)
ChamplainMapSource *map_source)
{
ChamplainMapSource *map_source = user_data->map_source;
ChamplainMapSource *next_source;
// frees user_data - must not be used later in the function
g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, map_source);
if (!map_source)
return;
next_source = champlain_map_source_get_next_source (map_source);
if (!data->error)
......@@ -287,17 +276,9 @@ tile_rendered_cb (ChamplainTile *tile,
}
else if (next_source)
champlain_map_source_fill_tile (next_source, tile);
}
static void
destroy_cb_data (TileRenderedData *data,
G_GNUC_UNUSED GClosure *closure)
{
if (data->map_source)
g_object_remove_weak_pointer (G_OBJECT (data->map_source), (gpointer *) &data->map_source);
g_slice_free (TileRenderedData, data);
g_object_unref (map_source);
g_object_unref (tile);
}
......@@ -323,7 +304,6 @@ fill_tile (ChamplainMapSource *map_source,
if (link)
{
QueueMember *member = link->data;
TileRenderedData *user_data;
move_queue_member_to_head (priv->queue, link);
......@@ -331,13 +311,10 @@ fill_tile (ChamplainMapSource *map_source,
g_return_if_fail (CHAMPLAIN_IS_RENDERER (renderer));
user_data = g_slice_new (TileRenderedData);
user_data->map_source = map_source;
g_object_add_weak_pointer (G_OBJECT (map_source), (gpointer *) &user_data->map_source);
g_object_ref (map_source);
g_object_ref (tile);
g_signal_connect_data (tile, "render-complete", G_CALLBACK (tile_rendered_cb),
user_data, (GClosureNotify) destroy_cb_data, 0);
g_signal_connect (tile, "render-complete", G_CALLBACK (tile_rendered_cb), map_source);
champlain_renderer_set_data (renderer, member->data, member->size);
champlain_renderer_render (renderer, tile);
......
......@@ -305,9 +305,6 @@ tile_loaded_cb (gpointer worker_data)
gchar *buffer = NULL;
gsize buffer_size;
if (tile)
g_object_remove_weak_pointer (G_OBJECT (tile), (gpointer *) &data->tile);
g_slice_free (WorkerThreadData, data);
if (!tile)
......@@ -360,6 +357,7 @@ finish:
if (cst)
cairo_surface_destroy (cst);
g_object_unref (renderer);
g_object_unref (tile);
g_free (buffer);
return FALSE;
......@@ -424,7 +422,7 @@ render (ChamplainRenderer *renderer,
data->tile = tile;
data->renderer = renderer;
g_object_add_weak_pointer (G_OBJECT (tile), (gpointer *) &data->tile);
g_object_ref (tile);
g_object_ref (renderer);
g_thread_pool_push (priv->thpool, data, &error);
......@@ -434,7 +432,7 @@ render (ChamplainRenderer *renderer,
g_error_free (error);
g_slice_free (WorkerThreadData, data);
g_object_unref (renderer);
g_object_remove_weak_pointer (G_OBJECT (tile), (gpointer *) &data->tile);
g_object_unref (tile);
}
}
......
......@@ -366,26 +366,15 @@ champlain_network_bbox_tile_source_load_map_data (
}
typedef struct
{
ChamplainMapSource *map_source;
} TileRenderedData;
static void
tile_rendered_cb (ChamplainTile *tile,
ChamplainRenderCallbackData *data,
TileRenderedData *user_data)
ChamplainMapSource *map_source)
{
ChamplainMapSource *map_source = user_data->map_source;
ChamplainMapSource *next_source;
// frees user_data - must not be used later in the function
g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, map_source);
if (!map_source)
return;
next_source = champlain_map_source_get_next_source (map_source);
if (!data->error)
......@@ -402,17 +391,9 @@ tile_rendered_cb (ChamplainTile *tile,
}
else if (next_source)
champlain_map_source_fill_tile (next_source, tile);
}
static void
destroy_cb_data (TileRenderedData *data,
G_GNUC_UNUSED GClosure *closure)
{
if (data->map_source)
g_object_remove_weak_pointer (G_OBJECT (data->map_source), (gpointer *) &data->map_source);
g_slice_free (TileRenderedData, data);
g_object_unref (map_source);
g_object_unref (tile);
}
......@@ -428,19 +409,15 @@ fill_tile (ChamplainMapSource *map_source,
if (champlain_tile_get_state (tile) != CHAMPLAIN_STATE_LOADED)
{
ChamplainRenderer *renderer;
TileRenderedData *user_data;
renderer = champlain_map_source_get_renderer (map_source);
g_return_if_fail (CHAMPLAIN_IS_RENDERER (renderer));
user_data = g_slice_new (TileRenderedData);
user_data->map_source = map_source;
g_object_add_weak_pointer (G_OBJECT (map_source), (gpointer *) &user_data->map_source);
g_object_ref (map_source);
g_object_ref (tile);
g_signal_connect_data (tile, "render-complete", G_CALLBACK (tile_rendered_cb),
user_data, (GClosureNotify) destroy_cb_data, 0);
g_signal_connect (tile, "render-complete", G_CALLBACK (tile_rendered_cb), map_source);
champlain_renderer_render (renderer, tile);
}
......
......@@ -81,10 +81,17 @@ struct _ChamplainNetworkTileSourcePrivate
SoupSession *soup_session;
};
typedef struct
{
ChamplainMapSource *map_source;
SoupMessage *msg;
} TileCancelledData;
typedef struct
{
ChamplainMapSource *map_source;
ChamplainTile *tile;
TileCancelledData *cancelled_data;
} TileLoadedData;
typedef struct
......@@ -93,14 +100,13 @@ typedef struct
gchar *etag;
} TileRenderedData;
typedef struct
{
ChamplainMapSource *map_source;
SoupMessage *msg;
} TileDestroyedCbData;
static void fill_tile (ChamplainMapSource *map_source,
ChamplainTile *tile);
static void
tile_state_notify (ChamplainTile *tile,
G_GNUC_UNUSED GParamSpec *pspec,
TileCancelledData *data);
static gchar *get_tile_uri (ChamplainNetworkTileSource *source,
gint x,
......@@ -530,16 +536,11 @@ tile_rendered_cb (ChamplainTile *tile,
{
ChamplainMapSource *map_source = user_data->map_source;
ChamplainMapSource *next_source;
gchar *etag;
gchar *etag = user_data->etag;
etag = g_strdup (user_data->etag);
// frees user_data - must not be used later in the function
g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, map_source);
g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, user_data);
g_slice_free (TileRenderedData, user_data);
if (!map_source)
return;
next_source = champlain_map_source_get_next_source (map_source);
if (!data->error)
......@@ -561,20 +562,8 @@ tile_rendered_cb (ChamplainTile *tile,
champlain_map_source_fill_tile (next_source, tile);
g_free (etag);
}
static void
destroy_render_complete_data (TileRenderedData *data,
G_GNUC_UNUSED GClosure *closure)
{
if (data->map_source)
g_object_remove_weak_pointer (G_OBJECT (data->map_source), (gpointer *) &data->map_source);
if (data->etag)
g_free (data->etag);
g_slice_free (TileRenderedData, data);
g_object_unref (map_source);
g_object_unref (tile);
}
......@@ -593,31 +582,16 @@ tile_loaded_cb (G_GNUC_UNUSED SoupSession *session,
TileRenderedData *data;
ChamplainRenderer *renderer;
if (tile)
g_object_remove_weak_pointer (G_OBJECT (tile), (gpointer *) &callback_data->tile);
if (map_source)
g_object_remove_weak_pointer (G_OBJECT (map_source), (gpointer *) &callback_data->map_source);
g_signal_handlers_disconnect_by_func (tile, tile_state_notify, callback_data->cancelled_data);
g_slice_free (TileLoadedData, callback_data);
DEBUG ("Got reply %d", msg->status_code);
if (!tile)
{
DEBUG ("Tile destroyed while loading");
return;
}
else if (msg->status_code == SOUP_STATUS_CANCELLED)
if (msg->status_code == SOUP_STATUS_CANCELLED)
{
DEBUG ("Download of tile %d, %d got cancelled",
champlain_tile_get_x (tile), champlain_tile_get_y (tile));
return;
}
else if (!map_source)
{
DEBUG ("Map source destroyed");
return;
goto cleanup;
}
if (msg->status_code == SOUP_STATUS_NOT_MODIFIED)
......@@ -648,10 +622,7 @@ tile_loaded_cb (G_GNUC_UNUSED SoupSession *session,
data->map_source = map_source;
data->etag = g_strdup (etag);
g_object_add_weak_pointer (G_OBJECT (map_source), (gpointer *) &data->map_source);
g_signal_connect_data (tile, "render-complete", G_CALLBACK (tile_rendered_cb),
data, (GClosureNotify) destroy_render_complete_data, 0);
g_signal_connect (tile, "render-complete", G_CALLBACK (tile_rendered_cb), data);
champlain_renderer_set_data (renderer, msg->response_body->data, msg->response_body->length);
champlain_renderer_render (renderer, tile);
......@@ -661,17 +632,22 @@ tile_loaded_cb (G_GNUC_UNUSED SoupSession *session,
load_next:
if (next_source)
champlain_map_source_fill_tile (next_source, tile);
return;
goto cleanup;
finish:
champlain_tile_set_fade_in (tile, TRUE);
champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
champlain_tile_display_content (tile);
cleanup:
g_object_unref (tile);
g_object_unref (map_source);
}
static void
destroy_cb_data (TileDestroyedCbData *data,
destroy_cancelled_data (TileCancelledData *data,
G_GNUC_UNUSED GClosure *closure)
{
if (data->map_source)
......@@ -680,15 +656,16 @@ destroy_cb_data (TileDestroyedCbData *data,
if (data->msg)
g_object_remove_weak_pointer (G_OBJECT (data->msg), (gpointer *) &data->msg);
g_slice_free (TileDestroyedCbData, data);
g_slice_free (TileCancelledData, data);
}
static void
tile_destroyed_cb (G_GNUC_UNUSED ChamplainTile *tile,
TileDestroyedCbData *data)
tile_state_notify (ChamplainTile *tile,
G_GNUC_UNUSED GParamSpec *pspec,
TileCancelledData *data)
{
if (data->map_source && data->msg)
if (champlain_tile_get_state (tile) == CHAMPLAIN_STATE_DONE && data->map_source && data->msg)
{
DEBUG ("Canceling tile download");
ChamplainNetworkTileSourcePrivate *priv = CHAMPLAIN_NETWORK_TILE_SOURCE (data->map_source)->priv;
......@@ -773,22 +750,23 @@ fill_tile (ChamplainMapSource *map_source,
g_free (date);
}
TileDestroyedCbData *tile_destroyed_cb_data = g_slice_new (TileDestroyedCbData);
tile_destroyed_cb_data->map_source = map_source;
tile_destroyed_cb_data->msg = msg;
TileCancelledData *tile_cancelled_data = g_slice_new (TileCancelledData);
tile_cancelled_data->map_source = map_source;
tile_cancelled_data->msg = msg;
g_object_add_weak_pointer (G_OBJECT (msg), (gpointer *) &tile_destroyed_cb_data->msg);
g_object_add_weak_pointer (G_OBJECT (map_source), (gpointer *) &tile_destroyed_cb_data->map_source);
g_object_add_weak_pointer (G_OBJECT (msg), (gpointer *) &tile_cancelled_data->msg);
g_object_add_weak_pointer (G_OBJECT (map_source), (gpointer *) &tile_cancelled_data->map_source);
g_signal_connect_data (tile, "destroy", G_CALLBACK (tile_destroyed_cb),
tile_destroyed_cb_data, (GClosureNotify) destroy_cb_data, 0);
g_signal_connect_data (tile, "notify::state", G_CALLBACK (tile_state_notify),
tile_cancelled_data, (GClosureNotify) destroy_cancelled_data, 0);
callback_data = g_slice_new (TileLoadedData);
callback_data->tile = tile;
callback_data->map_source = map_source;
callback_data->cancelled_data = tile_cancelled_data;
g_object_add_weak_pointer (G_OBJECT (tile), (gpointer *) &callback_data->tile);
g_object_add_weak_pointer (G_OBJECT (map_source), (gpointer *) &callback_data->map_source);
g_object_ref (map_source);
g_object_ref (tile);
soup_session_queue_message (priv->soup_session, msg,
tile_loaded_cb,
......
......@@ -75,26 +75,15 @@ champlain_null_tile_source_new_full (ChamplainRenderer *renderer)
}
typedef struct
{
ChamplainMapSource *map_source;
} TileRenderedData;
static void
tile_rendered_cb (ChamplainTile *tile,
ChamplainRenderCallbackData *data,
TileRenderedData *user_data)
ChamplainMapSource *map_source)
{
ChamplainMapSource *map_source = user_data->map_source;
ChamplainMapSource *next_source;
// frees user_data - must not be used later in the function
g_signal_handlers_disconnect_by_func (tile, tile_rendered_cb, map_source);
if (!map_source)
return;
next_source = champlain_map_source_get_next_source (map_source);
if (!data->error)
......@@ -111,17 +100,9 @@ tile_rendered_cb (ChamplainTile *tile,
}
else if (next_source)
champlain_map_source_fill_tile (next_source, tile);
}
static void
destroy_cb_data (TileRenderedData *data,
G_GNUC_UNUSED GClosure *closure)
{
if (data->map_source)
g_object_remove_weak_pointer (G_OBJECT (data->map_source), (gpointer *) &data->map_source);
g_slice_free (TileRenderedData, data);
g_object_unref (map_source);
g_object_unref (tile);
}
......@@ -137,19 +118,15 @@ fill_tile (ChamplainMapSource *map_source,
if (champlain_tile_get_state (tile) != CHAMPLAIN_STATE_LOADED)
{
ChamplainRenderer *renderer;
TileRenderedData *user_data;
renderer = champlain_map_source_get_renderer (map_source);
g_return_if_fail (CHAMPLAIN_IS_RENDERER (renderer));
user_data = g_slice_new (TileRenderedData);
user_data->map_source = map_source;
g_object_add_weak_pointer (G_OBJECT (map_source), (gpointer *) &user_data->map_source);
g_object_ref (map_source);
g_object_ref (tile);
g_signal_connect_data (tile, "render-complete", G_CALLBACK (tile_rendered_cb),
user_data, (GClosureNotify) destroy_cb_data, 0);
g_signal_connect (tile, "render-complete", G_CALLBACK (tile_rendered_cb), map_source);
champlain_renderer_render (renderer, tile);
}
......
......@@ -251,8 +251,6 @@ static void update_scale (ChamplainView *view);
static void view_load_visible_tiles (ChamplainView *view);
static void view_position_tile (ChamplainView *view,
ChamplainTile *tile);
static void view_update_state (ChamplainView *view,
ChamplainTile *tile);
static void view_update_anchor (ChamplainView *view,
gint x,
gint y);
......@@ -260,9 +258,9 @@ static gboolean view_set_zoom_level_at (ChamplainView *view,
gint zoom_level,
gint x,
gint y);
static void tile_state_notify (GObject *gobject,
GParamSpec *pspec,
gpointer data);
static void tile_state_notify (ChamplainTile *tile,
G_GNUC_UNUSED GParamSpec *pspec,
ChamplainView *view);
static void view_update_polygons (ChamplainView *view);
static gboolean finger_scroll_key_press_cb (ClutterActor *actor,
ClutterKeyEvent *event,
......@@ -273,8 +271,6 @@ static void champlain_view_go_to_with_duration (ChamplainView *view,
guint duration);
static gboolean perform_update_cb (ChamplainView *view);
static gboolean fill_tile_cb (FillTileCallbackData *data);
static void tile_destroyed_cb (GObject *gobject,
gpointer data);
#define SCALE_HEIGHT 20
#define SCALE_PADDING 10
......@@ -2536,7 +2532,12 @@ view_load_visible_tiles (ChamplainView *view)
if (tile_x < x_first || tile_x >= x_end ||
tile_y < y_first || tile_y >= y_end ||
zoom_level != priv->zoom_level)
clutter_container_remove_actor (CLUTTER_CONTAINER (priv->map_layer), CLUTTER_ACTOR (tile));
{
// inform map source to terminate loading the tile
if (champlain_tile_get_state (tile) != CHAMPLAIN_STATE_DONE)
champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
clutter_container_remove_actor (CLUTTER_CONTAINER (priv->map_layer), CLUTTER_ACTOR (tile));
}
else
{
tile_map[(tile_y - y_first) * x_count + (tile_x - x_first)] = TRUE;
......@@ -2579,9 +2580,7 @@ view_load_visible_tiles (ChamplainView *view)
data->tile = tile;
data->map_source = priv->map_source;
g_signal_connect (tile, "destroy", G_CALLBACK (tile_destroyed_cb), view);
g_object_add_weak_pointer (G_OBJECT (tile), (gpointer *) &data->tile);
g_object_ref (tile);
g_object_ref (priv->map_source);
/* set priority high, otherwise tiles will be loaded after panning is done */
......@@ -2608,14 +2607,11 @@ fill_tile_cb (FillTileCallbackData *data)
ChamplainTile *tile = data->tile;
ChamplainMapSource *map_source = data->map_source;
if (data->tile)
{
g_object_remove_weak_pointer (G_OBJECT (data->tile), (gpointer *) &data->tile);
champlain_map_source_fill_tile (map_source, tile);
}
champlain_map_source_fill_tile (map_source, tile);
g_slice_free (FillTileCallbackData, data);
g_object_unref (map_source);
g_object_unref (tile);
return FALSE;
}
......@@ -2658,44 +2654,12 @@ champlain_view_reload_tiles (ChamplainView *view)
static void
tile_destroyed_cb (GObject *gobject,
gpointer data)
{
DEBUG_LOG ()
ChamplainView *view = CHAMPLAIN_VIEW (data);
ChamplainTile *tile = CHAMPLAIN_TILE (gobject);
ChamplainViewPrivate *priv = view->priv;
if (champlain_tile_get_state (tile) == CHAMPLAIN_STATE_LOADING ||
champlain_tile_get_state (tile) == CHAMPLAIN_STATE_LOADED)
{
priv->tiles_loading--;
if (priv->tiles_loading == 0)
{
priv->state = CHAMPLAIN_STATE_DONE;
g_object_notify (G_OBJECT (view), "state");
}
}
}
static void
tile_state_notify (GObject *gobject,
tile_state_notify (ChamplainTile *tile,
G_GNUC_UNUSED GParamSpec *pspec,
gpointer data)
{
DEBUG_LOG ()
view_update_state (CHAMPLAIN_VIEW (data), CHAMPLAIN_TILE (gobject));
}
static void
view_update_state (ChamplainView *view, ChamplainTile *tile)
ChamplainView *view)
{
DEBUG_LOG ()
ChamplainState tile_state = champlain_tile_get_state (tile);
ChamplainViewPrivate *priv = view->priv;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment