Re: [Rhythmbox-devel] State Of The Rhythmbox (3)



I was just going through the conversion plan and fleshing it out a bit
more, and I realized that the RhythmDB locking scheme I had envisoned
won't quite work.  My original plan was to GDK_THREADS_LEAVE () when we
entered the database from the main thread, and then GDK_THREADS_ENTER ()
when leaving the database.  Unfortunately, after discussing the issue
with some GNOME hackers, I came to the conclusion that GtkTreeView
wouldn't like being reentered in multiple threads.  This definitely
throws a cramp into the RhythmDB style.

So I'm back to the drawing board for a little bit.   Here's the current
dump of my thoughts, which I've just committed to DESIGN on the rhythmdb
branch:

** Multithread-capable

We need to ensure that the UI doesn't block.  Generally this
means using threads.  This introduces a lot of locking issues
that need to be addressed.

The database should be also optimized for common operations,
and this definitely means reading.  Writing should be lower
priority, although we don't want to completely starve writers.

Because we need to support multiple backends, we can only really
support coarse-grained locking (i.e. one big global RW lock).

*** Multithreaded entry attribute changes

This issue is not as simple as one might think.  We definitely
want to be able to use threads for this - for example, after
the user has changed a bunch of songs on disk, we need
to update the UI to reflect those changes, incrementally.
That involves emitting a gtk_tree_model_row_changed signal, for
which we need to hold the GDK lock.

*** Deadlock 

We have to consider deadlock situations here, where one thread is
holding the GDK lock, and wants the database lock, and then another
thread is holding the db lock and wants the GDK lock.  In the old
design, the any other thread could grab the GDK lock to update the UI,
which is wrong.

*** RBEntryModel

In general, we don't want the various processing threads in
Rhythmbox to be aware that there is this huge slow UI to
keep updated.  Setting an attribute or delete an entry
shouldn't involve doing anything else besides calling the
function.

However, we do need to update the UI somehow.  The UI
is represented by the GtkTreeModel implementations
returned by a query.  Thus, one plan is to have an update
queue.  Whenever a thread other than the main one modifies
RhythmDB, we push an update notifier onto the queue.  Then,
we have another thread (besides the main one) dedicated
to processing this queue, and emitting the appropriate
row_changed signals.

**** GtkTreeModel mapping efficiency

In order to emit the row_changed signal, we will need
to efficiently look up a GtkTreeIter, given an entry.
Perhaps we have to write our own GtkTreeModel implementation
that combines a GHashTable and a GList?  Or just subclass
GtkListStore, and add a GHashTable index?

*** Deletions

Handling deletions well is important.  Currently
doing a "Select All" followed by "Delete" can take
some time.  Now, this works two ways.  First, the user
can request a deletion.  To handle this, we simply
queue deletion requests from the UI, and then have
a thread which processes those.

However, we also need to handle deletions from other
threads, such as the database processing thread.  This
brings up an issue - we cannot treat deletions like
other operations.  If an entry is deleted from the
database, but the UI isn't updated - the user may
try to change the properties of an entry that's
already been deleted.  How to solve this?

*** Additions

Additions fairly straightforward; we don't have
as many database consistency issues as deletions.  Basically
we just have a thread add something to the database, and then
queue a signal emission for the main UI, much like for property
changes.




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]