Re: Reverting to non-async file chooser



On Fri, 2006-08-18 at 11:55 +0200, Tim Janik wrote:

> the reason we didn't have these semantics in the first place is that
> because the file operations may be executed *asyncronously*, cancellation
> can fail.

Yes, cancellation can fail, but it turns out that you normally don't
care about that.  GnomeVFS's async operations have the same assumptions,
and they work just fine.

The only funny case is where you have an open(), since it gives you back
a file descriptor.  Since GtkFileSystem has no operation that returns an
open file descriptor, this is not an issue for GTK+.

> consequently, the user gets to implement really complex semantics, if
> his general code that sets up the callback, and the callback implementation
> itself have to cover all the cases of:
> - callback is set up, request succeeds, callback frees closure;
> - callback is set up, request fails, callback frees closure;
> - callback is set up, request is cancelled, file system operation also
>    gets cancelled, outer code frees callback closure;
> - callback is set up, request is cancelled, file system operation completes
>    regardless (without notification!), outer code frees callback closure;

This is *exactly* the situation we have right now!  And callbacks have
to do a lot of extra work of managing the handle's memory, since none of
them care whether the operation was cancelled.

I'm going to change the current scheme to this:

- Canceling an operation guarantees that the callback is not called.
This lets you assume that you won't have invalid pointers in your
closure.

- Handles are opaque cookies.  You don't have to do memory management
for them.

- You are responsible for cleanup if you decide to do cancellation.
This is trivial to do, since you already have to keep knowledge on which
operations are running.  Async callbacks are not like signals:  you
*know* that they will be called unless you cancel them, because you
requested them in the first place; with signals, you never know when one
will come in.

> >  By that time, it
> >  is very likely that the closure of the callback is no longer valid.
> >  So, we want to get rid of it as soon as possible.
> 
> there are two ways to handle this properly, in a way that doesn't need
> to intermix cancellation semantics with closure/memory maintenance.
> if your closure references an object that the callback needs, you
> can either forcefully keep that object alive through a reference
> count until the closures gets freed (which can be early enough with
> a high prio idler), or you set a flag in the closure/nullify the
> object pointer in the closure once the object becomes invalid, so the
> callback can tell it's not supposed to treat the reference as valid.

This gets complicated very quickly, and requires a lot of support code.
A scheme like GnomeVFS's requires no particular intelligence from the
caller.

> >  Caveat:  gnome-vfs does not let you cancel the operation of mounting
> >  a drive or volume.  So if you cancel the handle from
> >  gtk_file_system_volume_mount(), your callback will not be called,
> >  but the volume *will* be mounted (unless an error occurs during
> >  mounting, of course).
> 
> i really consider this scenrio a MUST-NOT-HAPPEN (sorry for the caps ;)
> simply because it renders the _combination_ of two _vital_ features
> unusable (unreliable), namely cancellation of operations and notification
> about the success of operations.

In the particular case of volume mounts, you really do not care if the
operation happens even if you cancel it.  Canceling it simply means
"don't call my callback because I'm dying soon".  The user will see a
volume icon appear elsewhere in his desktop.

Remember than cancellation is there simply to 

a) change contexts.  The user got impatient and closed the file chooser
window, or he went to another directory before the current one got
loaded.

b) make cleanup easy.  You don't want callbacks to have to worry that
their surrounding context is dead.

c) have the possibility of saving a little bit of work if (a) happens
before the actual operation takes place in the worker thread.

Not to sound patronizing, but I already rewrote the cancellation layer
in GnomeVFS one time, so I know what I'm talking about ;)

  Federico




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