GIO: How to deal with blocks as async callbacks


#1

OK, so if the user passes a block to an *_async method it gets called
when the GAsyncReadyCallback is called. However, if any errors are
reported from the *_finish function they get raised. My question is
how to deal with this. I mean, where will one be able to catch the
error?

begin
GFile.new(…).read_async{ |contents| p contents }
rescue => e
p e.message
end

won’t work, if my reasoning is correct, as #read_async returns
immediately and the block might be called at a later time when the
begin-rescue-end block has been exited. Does anyone have any
suggestions on how to deal with this?

Thanks.

(I’m nearly done, by the way. This is more or less the only remaining
big issue.)


#2

Hi,

In removed_email_address@domain.invalid
“[ruby-gnome2-devel-en] GIO: How to deal with blocks as async
callbacks” on Thu, 26 Mar 2009 19:17:31 +0100,
Nikolai W. removed_email_address@domain.invalid wrote:

end
Is the example right usage?

It seems that here is an expected usage in GIO reference manual:

file = GLib::File.new(…)
file.read_async do |_file, res|
begin
stream = _file.finish(res)
p stream.read
rescue => e
p e.message
end
end

(I’m nearly done, by the way. This is more or less the only remaining
big issue.)

Great!
We’re looking forward to merge your work into Ruby/GLib2.

Thanks,

kou


#3

On Fri, Mar 27, 2009 at 13:57, Kouhei S. removed_email_address@domain.invalid wrote:

Nikolai W. removed_email_address@domain.invalid wrote:

file = GLib::File.new(…)
file.read_async do |_file, res|
begin
stream = _file.read_async_finish(res)
p stream.read
rescue => e
p e.message
end
end

Hm. Crap. Yeah, perhaps that’s how we should implement it. I wanted
to make it as easy to use as possible so that the C code calls finish
for you and just gives you the stream or whatever.

Is there no way of getting this to work as I suggested above?

I guess one can at least simplify it slightly by having something like
the following instead:

GLib::File.new(…).read_async do |result|
begin
p result.finish.read
rescue => e
p e.message
end
end

where result would be an intermediate object that would cary the state
of the operation (that is, any reported error and any actual result,
like the GInputStream), throwing any reported error when #finish is
invoked or returning the actual result. Perhaps not very smart to
cause the delay between calling the C function and getting the error
and then only reporting it when the Ruby #finish method gets called.
What do you think?

The Python bindings implement it the way you suggest.

F**k it. I’ll implement it like you suggest. It won’t have to change
that much code.

Thanks for clarifying!


#4

Hi,

In removed_email_address@domain.invalid
“Re: [ruby-gnome2-devel-en] GIO: How to deal with blocks as async
callbacks” on Fri, 27 Mar 2009 14:47:17 +0100,
Nikolai W. removed_email_address@domain.invalid wrote:

Is the example right usage?
end

GLib::File.new(…).read_async do |result|
begin
p result.finish.read
rescue => e
p e.message
end
end

If I implement it with what you suggested API, I’ll add an
API to register error handler callback:

file = GLib::File.new(…)
file.on_error_or_something do |exception|
p exception
end
file.read_async do |content|
p content
end

Thanks,

kou


#5

On Fri, Mar 27, 2009 at 14:55, Kouhei S. removed_email_address@domain.invalid wrote:

If I implement it with what you suggested API, I’ll add an
API to register error handler callback:

file = GLib::File.new(…)
file.on_error_or_something do |exception|
p exception
end
file.read_async do |content|
p content
end

Hm, that doesn’t feel very Rubyish either. I’ll go with your first
suggestion of having it look more like the C code.


#6

having it look more like the C code.

I think you could always opt for the easier way to implement, and if
it sucks using it that way it could be changed lateron.

Like how Gtk.init is no longer mandatory, and I think it is a good
change that it is no longer mandatory. :slight_smile: