Re: [Vala] Implicit lamdas/closures
- From: Sam Liddicott <sam liddicott com>
- To: vala-list gnome org
- Subject: Re: [Vala] Implicit lamdas/closures
- Date: Tue, 16 Sep 2008 13:48:58 +0100
Based on the idea I posted last night, I've done a proof-of-concept for
what I'm going to rename for the third time as "unrolled continuations"
which allows asynchronous clients (in server-client relationship) to be
coded synchronously but still implemented asynchronously by means of
continuations. This is most useful where the client also happens to be
an asynchronous server as samba4 is in my case.
The work is built upon the (not yet written) local variable lambda
support for vala.
I have for download a small vala project that uses the gtk event loop to
drive asynchronous handlers for continuations.
http://www.liddicott.com/~sam/sam/contin-0.1.0.tar.gz
When running the demo, if you click on the first button it makes an
basic rpc server object and issues an async request.
Click on the second button to answer that request.
When the answer is received a loop commences which issues 3 more
requests that need responding too.
Altogether the respond button is clicked 4 times, final response is then
ready to send back to the non-existent client.
This shows off that continuations can break-off and carry-on halfway
through a loop.
This all makes more sense after reviewing rpc_server.vala and rpc_server.c
rpc_server.vala uses a notation I will discuss below, but of course vala
can't handle this, so rpc_server.c and rpc_server.h have been severely
tweaked to have the form which I think ought to be generated.
I'm proposing a concept of inline lambdas that are supported using C's
label notation; e.g.
int a_function(int x) {
do_something(x);
a_label:
do_someting_else(x);
and within a_function, "a_label" can be used as if it were a function
pointer which internally takes 1 void* parameter which points to the
heap-allocated locals as is currently on the roadmap for lambda functions.
The labels and heap-allocated local variables allow a callback to
continue part-way through the function as if it had never left off.
I also propose this extended notation where parameters can follow the
label. If the parameters are already declared as local variables then
the type could (must?) be omitted.
They are a means of the callback passing extra data for cases where the
callback provides more than just a void* private data parameter.
It is important to realise that the label could also be reached WITHOUT
a callback occuring so the default value is also used to initialize the
local variable as well as a default parameter when (if) the callback
occurs. (Hmmm... do default parameters work for delegates?)
e.g.
int a_function(int x = 100) {
do_something(x);
// note that the label also has parameters
a_label(int y = 10):
do_something....
so that the generated wrapper will be declared something like:
int a_function__a_label(a_function__local_vars *vars, int y) {
vars->y=y;
return a_function__body(vars,1);
}
where the 2nd parameter 1 signifies the first label that a case
statement at the top of in a_function__body will "goto" (see below)
The a_function will generate two C functions, one to prepare and
initalize the heap:
int a_function(int x) {
struct a_function_vars vars=malloc(sizeof(struct a_function_vars));
vars->parameters.x=x;
vars->locals.y=10;
return a_function__body(vars, 0);
}
and then the real function body:
static int a_function__body(struct a_function__vars *vars, int label) {
switch (label) {
case 0: break;
case 1: goto a_label;
}
do_something(vars->locals.x);
a_label:
...
...
So, when making an async call that wants to use the rest of the function
as a continuation:
int a_function(int x) {
request_callback(next_position);
return;
next_position:
// do some more here
return;
}
For purity the async "return" maybe should be hidden? For samba4 I'll be
using a vapi-wrapped C macro which checks that the callback was
allocated and then returns so vala won't even know there was a return -
which also aids readability, but the other problem is that if vala knows
there is a return it starts unref'ing al the local variables which is
clearly wrong for a lambda - I guess vala will have to deal with this
when it finishes lambda support.
I imagine the heap-allocated local-vars struct will be ref-counted, so
that the variables will all get free'd when there are no more
continuation references.
Otherwise maybe all the heap-allocated local vars could be explicitly
freed with "finally return" or some such strong hint.
Maybe for even better neatness we want an implicit label called "next"
or something, which if used causes vala to effectively insert a
return_default after this vala statement, and imply a label following that..
Sam
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]