Re: Reverting to non-async file chooser



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
 cookies.

- 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
 as appropriate.

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.
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
in progress).
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
 make sense.

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?

 Federico

---
ciaoTJ



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