Re: GCancellable is not really cancellable?



Hi Alexander,

On Mon, Apr 26, 2010 at 2:59 PM, Alexander Larsson <alexl redhat com> wrote:
> On Sun, 2010-04-25 at 22:05 +0300, Felipe Contreras wrote:
>
>> So what am I supposed to do? ref() the object each time I do an async
>> operation, and unref() it each time the operation finishes, while also
>> keeping an extra field in order to find out if the object has been
>> disposed?
>
> Depends on what you mean by "object". The stream itself is automatically
> refed when there is an outstanding async operation on it. If you have
> further data that you need to live until the callback then you have to
> ref it, or otherwise keep it alive.

By "object" I mean my custom object that I passed through user_data.

>> What's the point? Wouldn't it be better to truly cancel the operation?
>
> This is how cancellation worked in gnome-vfs, and it has a few problems.

This how all I/O API's I know work; GIOChannel, libpurple, libevent.
They have no problems.

> First of all, its inherently and unfixably racy in the multi-threaded
> case. For instance, what if you call cancel() on a thread when the
> operation just finished and we've called the callback on another cpu.
> There is no way at this point to stop that emission, and its not
> reasonably possible to synchronize and have the cancel fail.

That's what mutexes are for. The cancel() function would wait until
the emission finishes.

> Secondly, its not always possible to immediately cancel an i/o
> operation, and the data passed to such an operation (for instance the
> destination buffer) need to stay around until the operation is really
> done, or you might be scribbling over random memory.

Ditto.

> Third, code wise its actually not simpler, because you now get two
> codepaths that free the data that was allocated for the data (free in
> callback, or free after cancelling). This leads to convoluted code that
> is hard to get right. With gio you can *always* assume the callback will
> be called, and only once, so you can free any data there.

If you want to free the data in the callback, then don't call
cancel(). Or make cancel() wait until the callback function has been
called, and then continue.

Perhaps a better solution would be to have a separate discard()
function that would cancel(), discard the results, and wait for the
callback to finish if it's in progress.

I don't think this scenario, where an object has ownership of a
GAsyncResult operation and updates itself on the callback, is uncommon
at all, and the current API is clearly not suited for this. If I want
to kill the operation, I should be able to, otherwise resources will
be wasted.

Cheers.

-- 
Felipe Contreras


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