Re: Reverting to non-async file chooser
- From: Tim Janik <timj imendio com>
- To: Federico Mena Quintero <federico ximian com>
- Cc: "release-team gnome org" <release-team gnome org>, GTK+ development mailing list <gtk-devel-list gnome org>, Matthias Clasen <matthias clasen gmail com>, Kristian Rietveld <kris imendio com>
- Subject: Re: Reverting to non-async file chooser
- Date: Fri, 18 Aug 2006 11:55:12 +0200 (CEST)
On Thu, 17 Aug 2006, Federico Mena Quintero wrote:
Semantics of callbacks and cancellation
- You need to hit the idle loop for your callback to be called, just
like in GnomeVFS.
- You do not need to ever ref/unref async handles; they are opaque
- Once you call gtk_file_system_cancel_operation(), you can assume
that the callback corresponding to the handle will NOT be called.
Therefore, the caller must free the stuff in the callback's closure
the reason we didn't have these semantics in the first place is that
because the file operations may be executed *asyncronously*, cancellation
that is, you request anoperation to be cancelled, but the op was/is
carried out regardlessly (e.g. because it might be atomic and already
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;
so the idea was to instead:
- always call the callback, so no notification ever gets lost and so
cleaning up of its closure is simple, since there's only a single
code portion that does it;
- allow cancellation to fail. i.e. for succesfull operations that can't
reasonably be rolled back, a cancellation request is simply ignored
if it arrives too late. and it's of course important to still call
the callback here, so both cases (succeeding cancellation and ignored
cancellation) can be handled.
Rationale: the idle loop may be far away in time.
that is easily fixed. if the current code just queues an ordinary idle
handler, and you notice that's too late, it can be queued at priority
G_PRIORITY_DEFAULT, which results in the handler be called round-robin
with event handling. or, if that may still be too late, you can enqueue
it with priority G_PRIORITY_HIGH, which will allmost always execute your
handler right after the current main loop call stack has returned.
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.
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.
Notes: The current scheme (callbacks get called even when
cancelled; caller must unref the handle in the callback) doesn't
i tend to disagree, or at least i don't fully understand you here.
can you point out what specific problem you're actually having with
the scheme outlined above?
Callbacks test if the handle being passed is the same
that got remembered; this causes leaks if an old handle had been
canceled but the idle loop did not run yet.
hm, i thought handles are being freed by the file system code, and
regardless of what the user provided callback actually does.
so where exactly is the leak in this?
] [Thread Prev