Re: GCancellable hints



On Thu, 2009-08-27 at 08:09 +0000, Benjamin Otte wrote:
> In an async program, the 
> same cancellable is often used for multiple calls at the same time. 

Be careful, however, to avoid using the same cancellable for multiple
simultaneous operations. The docs clearly state

 One GCancellable can be used in multiple consecutive operations,
 but not in multiple concurrent operations.

And here's why when I asked Alex why this is so

 <alexl> davidz: Take the case of two readers using the same cancellable
 <alexl> davidz: the cancel will write to the pipe, etc
 <alexl> davidz: with the right race condition, phase of the moon
 etc, we may only wake up one of the threads

> What you want is a way to describe a transaction, where the caller and
> the  function call interact in two directions and one of the
> interactions is  cancellation while another interaction is telling the
> caller that cancellation  is currently disabled. Other transaction
> information you probably have in PackageKit is progress information.

Right. If you are interacting with a D-Bus service the best practice
involves having separate remote Job objects for long-running operations.
Then the usage is kinda like this (in pseudo-code) - we're calling the
bar() method on the Foo interface on the baz object.

 job_object_path = daemon_foo_bar_sync (baz);
 job = new_proxy (connection, job_path, "org.foo.Job");
 g_signal_connect (job, "completed", callback, user_data);

E.g. starting an operation amounts to calling a remote method that
immediately returns an object path to the job object. You'd abort the
operation with a remote method on the job object. E.g. no use of
GCancellable at all for this. However you do want to use GCancellable to
do this async, e.g. use daemon_invoke_method_async().

When the job is completed you can then call another remote method to get
the result of the job (if applicable) or maybe the completed signal will
have the value as a variant (and maybe the completed signal is only
emitted to the name who invoked the method).

E.g. the proposal is to use the same foo_async(), foo_finish() pattern
used in GIO - only via IPC.

The benefit of doing things this way is that other processes may cancel
the job as well - they'd just enumerate all the job objects. They would
also be able to extract other kinds of information about the job - who
started it, what is the completion state, what is the name/identifier
for the job, whether it is currently abortable (trying to avoid the word
cancellable here) and so forth. These things would probably be
properties on the Job object.

(FWIW, DeviceKit-disks works roughly like this - the job objects are not
separate objects though - for now they are just properties on the Device
object on which the operation was started. But I'm planning to rework
things to work like what I sketched out above.)

     David




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