Luca Bruno wrote:
> All correct.
Thanks.
> > Question: At the C level, I guess this first calls forwards to
> > 'other_method' to start it before returning to the caller due to the
> > 'yield'. If the 'other_method' also yields, then there is no
> > problem, but if 'other_method' finishes without yielding (e.g. if it
> > can return the result right away without doing any asynchronous
> > work), then the 'method' callback would be called again, only a few
> > stack frames lower. In theory if 'method' called 'other_method'
> > repeatedly like this, the stack could overflow. Is this correct?
> > If so maybe that needs documenting.
>
> Variables in async methods are allocated on the heap. By the way I
> think I didn't understand well the problem you're raising.
The generated C code sometimes uses 'g_simple_async_result_complete',
and sometimes 'g_simple_async_result_complete_in_idle'. There are
cases where if it used 'g_simple_async_result_complete', then the C
stack could grow and grow. However, I tried writing some code to
provoke this situation, and it used the *_idle call in this case and
didn't fail. So perhaps Joerg already thought of this case.
Here was the test case:
async void tester() {
// Call read_item for values it returns right away, trying to
// provoke stack overflow from the callbacks
for (int a = 0; a<2000000; a+=2) {
var val = yield read_item(a);
}
}
async string read_item(int a) {
if (a % 2 == 0) {
// Pretend we have it in cache and can return right away
return @"Value: $a";
} else {
// Pretend that this is a value that we need to fetch over the
// network, so we yield and return the value some time later
Idle.add(read_item.callback);
yield;
return @"Value: $a";
}
}
void main(string[] args) {
var loop = new MainLoop();
tester.begin((obj, res) => {
tester.end(res);
loop.quit();
});
loop.run();
}
> > - Call with .begin(). Question: Is this just like the 'method()' call
> > but adding a callback request for when method() finishes? If so
> > will it also just run until the first 'yield' and then return?
> >
> > method.begin(args, callback);
>
> Yes.
>
> > - Call with .end(). For use within the 'begin' callback, to get
> > method return value and clean up. Question: Is an .end() call
> > required for plain 'method()' style invocation?
> >
> > method.end(out_args);
>
> Can you rephrase?
We can call 'method' either like this:
method();
or like this:
method.begin();
or like this:
method.begin((obj, res) => {
method.end(res);
});
In the first two cases, is the .end() handled automatically? Looking
at the generated code, it doesn't seem so. Could this be a problem?
For example, could this cause a leak?
> > Also, questions:
> >
> > - Are there any other special features associated with async methods?
> > (Any other .<identifier> features, for example.)
> >
>
> No.
>
> > - When it is necessary to have a main loop running? Some of the
> > generated C code requests an idle callback. I guess this won't work
> > without a main loop running. But the Generator, for example, seems
> > to run through fine without a main loop.
>
> Mainloop is required only for async methods that never use yield.
>
> >
> > - The docs say "The .callback call is used to implicitly register a
> > _finish method for the async method". What does this mean? Also:
> > "end() is a syntax for the *_finish method". I'm confused.
>
> Try looking at the generated C code.
I think the second phrase makes sense. The first phrase doesn't seem
correct: "The .callback call is used to implicitly register a _finish
method for the async method".
Who owns the Vala Tutorial? I could add more info to the Tutorial,
but if that isn't okay I will create a new wiki page.
Jim
--
Jim Peters (_)/=\~/_(_) [email protected]
(_) /=\ ~/_ (_)
UazĂș (_) /=\ ~/_ (_) http://
in Peru (_) ____ /=\ ____ ~/_ ____ (_) uazu.net
_______________________________________________
vala-list mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/vala-list