rhythmbox r6063 - in trunk: . rhythmdb
- From: jmatthew svn gnome org
- To: svn-commits-list gnome org
- Subject: rhythmbox r6063 - in trunk: . rhythmdb
- Date: Mon, 17 Nov 2008 08:59:39 +0000 (UTC)
Author: jmatthew
Date: Mon Nov 17 08:59:39 2008
New Revision: 6063
URL: http://svn.gnome.org/viewvc/rhythmbox?rev=6063&view=rev
Log:
2008-11-17 Jonathan Matthew <jonathan d14n org>
* rhythmdb/rhythmdb-private.h:
* rhythmdb/rhythmdb.c: (rhythmdb_dispose), (free_entry_changes),
(rhythmdb_emit_entry_signals_idle), (process_changed_entries_cb),
(sync_entry_changed), (rhythmdb_commit_internal):
Rather than emitting entry-changed signals as part of rhythmdb_commit,
marshal the data over to the main thread as is done for entry-added
and entry-deleted. Take the gdk lock before emitting any of those
signals. Fixes any number of weird crashes, as well as deadlocks
after podcast downloads when a11y is enabled. #362725.
Modified:
trunk/ChangeLog
trunk/rhythmdb/rhythmdb-private.h
trunk/rhythmdb/rhythmdb.c
Modified: trunk/rhythmdb/rhythmdb-private.h
==============================================================================
--- trunk/rhythmdb/rhythmdb-private.h (original)
+++ trunk/rhythmdb/rhythmdb-private.h Mon Nov 17 08:59:39 2008
@@ -184,6 +184,7 @@
guint emit_entry_signals_id;
GList *added_entries_to_emit;
GList *deleted_entries_to_emit;
+ GHashTable *changed_entries_to_emit;
gboolean can_save;
gboolean saving;
Modified: trunk/rhythmdb/rhythmdb.c
==============================================================================
--- trunk/rhythmdb/rhythmdb.c (original)
+++ trunk/rhythmdb/rhythmdb.c Mon Nov 17 08:59:39 2008
@@ -135,9 +135,6 @@
RhythmDBEntry *entry,
const gchar *realuri);
-static gboolean free_entry_changes (RhythmDBEntry *entry,
- GSList *changes,
- RhythmDB *db);
static gboolean rhythmdb_idle_save (RhythmDB *db);
static void library_location_changed_cb (GConfClient *client,
guint cnxn_id,
@@ -906,6 +903,9 @@
g_list_foreach (db->priv->added_entries_to_emit, (GFunc)rhythmdb_entry_unref, NULL);
g_list_foreach (db->priv->deleted_entries_to_emit, (GFunc)rhythmdb_entry_unref, NULL);
+ if (db->priv->changed_entries_to_emit != NULL) {
+ g_hash_table_destroy (db->priv->changed_entries_to_emit);
+ }
}
if (db->priv->metadata != NULL) {
@@ -1081,57 +1081,17 @@
}
}
-static gboolean
-free_entry_changes (RhythmDBEntry *entry,
- GSList *changes,
- RhythmDB *db)
+static void
+free_entry_changes (GSList *entry_changes)
{
GSList *t;
- for (t = changes; t; t = t->next) {
+ for (t = entry_changes; t; t = t->next) {
RhythmDBEntryChange *change = t->data;
g_value_unset (&change->old);
g_value_unset (&change->new);
g_slice_free (RhythmDBEntryChange, change);
}
- g_slist_free (changes);
-
- return TRUE;
-}
-
-static void
-emit_entry_changed (RhythmDBEntry *entry,
- GSList *changes,
- RhythmDB *db)
-{
- g_signal_emit (G_OBJECT (db), rhythmdb_signals[ENTRY_CHANGED], 0, entry, changes);
-}
-
-static void
-sync_entry_changed (RhythmDBEntry *entry,
- GSList *changes,
- RhythmDB *db)
-{
- GSList *t;
-
- for (t = changes; t; t = t->next) {
- RBMetaDataField field;
- RhythmDBEntryChange *change = t->data;
-
- if (metadata_field_from_prop (change->prop, &field)) {
- RhythmDBAction *action;
-
- if (!rhythmdb_entry_is_editable (db, entry)) {
- g_warning ("trying to sync properties of non-editable file");
- break;
- }
-
- action = g_slice_new0 (RhythmDBAction);
- action->type = RHYTHMDB_ACTION_SYNC;
- action->uri = rb_refstring_ref (entry->location);
- g_async_queue_push (db->priv->action_queue, action);
- break;
- }
- }
+ g_slist_free (entry_changes);
}
static gboolean
@@ -1139,7 +1099,11 @@
{
GList *added_entries;
GList *deleted_entries;
+ GHashTable *changed_entries;
GList *l;
+ GHashTableIter iter;
+ RhythmDBEntry *entry;
+ GSList *entry_changes;
/* get lists of entries to emit, reset source id value */
g_mutex_lock (db->priv->change_mutex);
@@ -1150,24 +1114,43 @@
deleted_entries = db->priv->deleted_entries_to_emit;
db->priv->deleted_entries_to_emit = NULL;
+ changed_entries = db->priv->changed_entries_to_emit;
+ db->priv->changed_entries_to_emit = NULL;
+
db->priv->emit_entry_signals_id = 0;
g_mutex_unlock (db->priv->change_mutex);
+ GDK_THREADS_ENTER ();
+
+ /* emit changed entries */
+ if (changed_entries != NULL) {
+ g_hash_table_iter_init (&iter, changed_entries);
+ while (g_hash_table_iter_next (&iter, (gpointer *)&entry, (gpointer *)&entry_changes)) {
+ g_signal_emit (G_OBJECT (db), rhythmdb_signals[ENTRY_CHANGED], 0, entry, entry_changes);
+ g_hash_table_iter_remove (&iter);
+ }
+ }
+
/* emit added entries */
for (l = added_entries; l; l = g_list_next (l)) {
- RhythmDBEntry *entry = (RhythmDBEntry *)l->data;
+ entry = (RhythmDBEntry *)l->data;
g_signal_emit (G_OBJECT (db), rhythmdb_signals[ENTRY_ADDED], 0, entry);
rhythmdb_entry_unref (entry);
}
/* emit deleted entries */
for (l = deleted_entries; l; l = g_list_next (l)) {
- RhythmDBEntry *entry = (RhythmDBEntry *)l->data;
+ entry = (RhythmDBEntry *)l->data;
g_signal_emit (G_OBJECT (db), rhythmdb_signals[ENTRY_DELETED], 0, entry);
rhythmdb_entry_unref (entry);
}
+ GDK_THREADS_LEAVE ();
+
+ if (changed_entries != NULL) {
+ g_hash_table_destroy (changed_entries);
+ }
g_list_free (added_entries);
g_list_free (deleted_entries);
return FALSE;
@@ -1239,24 +1222,69 @@
return TRUE;
}
+static gboolean
+process_changed_entries_cb (RhythmDBEntry *entry,
+ GSList *changes,
+ RhythmDB *db)
+{
+ if (db->priv->changed_entries_to_emit == NULL) {
+ db->priv->changed_entries_to_emit = g_hash_table_new_full (NULL,
+ NULL,
+ (GDestroyNotify) rhythmdb_entry_unref,
+ (GDestroyNotify) free_entry_changes);
+ }
+
+ g_hash_table_insert (db->priv->changed_entries_to_emit, rhythmdb_entry_ref (entry), changes);
+ return TRUE;
+}
+
+static void
+sync_entry_changed (RhythmDBEntry *entry,
+ GSList *changes,
+ RhythmDB *db)
+{
+ GSList *t;
+
+ for (t = changes; t; t = t->next) {
+ RBMetaDataField field;
+ RhythmDBEntryChange *change = t->data;
+
+ if (metadata_field_from_prop (change->prop, &field)) {
+ RhythmDBAction *action;
+
+ if (!rhythmdb_entry_is_editable (db, entry)) {
+ g_warning ("trying to sync properties of non-editable file");
+ break;
+ }
+
+ action = g_slice_new0 (RhythmDBAction);
+ action->type = RHYTHMDB_ACTION_SYNC;
+ action->uri = rb_refstring_ref (entry->location);
+ g_async_queue_push (db->priv->action_queue, action);
+ break;
+ }
+ }
+}
+
+
static void
rhythmdb_commit_internal (RhythmDB *db,
gboolean sync_changes,
GThread *thread)
{
g_mutex_lock (db->priv->change_mutex);
-
- g_hash_table_foreach (db->priv->changed_entries, (GHFunc) emit_entry_changed, db);
- if (sync_changes)
+
+ if (sync_changes) {
g_hash_table_foreach (db->priv->changed_entries, (GHFunc) sync_entry_changed, db);
- g_hash_table_foreach_remove (db->priv->changed_entries, (GHRFunc) free_entry_changes, db);
+ }
- /* update the lists of entry added/deleted signals to emit */
+ /* update the sets of entry changed/added/deleted signals to emit */
+ g_hash_table_foreach_remove (db->priv->changed_entries, (GHRFunc) process_changed_entries_cb, db);
g_hash_table_foreach_remove (db->priv->added_entries, (GHRFunc) process_added_entries_cb, db);
g_hash_table_foreach_remove (db->priv->deleted_entries, (GHRFunc) process_deleted_entries_cb, db);
/* if there are some signals to emit, add a new idle callback if required */
- if (db->priv->added_entries_to_emit || db->priv->deleted_entries_to_emit) {
+ if (db->priv->added_entries_to_emit || db->priv->deleted_entries_to_emit || db->priv->changed_entries_to_emit) {
if (db->priv->emit_entry_signals_id == 0)
db->priv->emit_entry_signals_id = g_idle_add ((GSourceFunc) rhythmdb_emit_entry_signals_idle, db);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]