[Ur] callbacks from C FFI (again)
Adam Chlipala
adamc at csail.mit.edu
Sun Jan 5 13:10:48 EST 2014
On 01/03/2014 04:39 PM, Sergey Mironov wrote:
> Here is how I view the uw_trigger_task("name_of_task") you are suggesting:
> [...]
>
> This time JobFFI.run remembers task name and calls uw_trigger_task
> upon completion. Do I understand your idea correctly?
>
Yes, that's what I meant.
> I have doubts. In my view, the whole concept of tasks is a kind of
> compromise. It covers some certain cases of server-side procedures
> without introducing a low-level bindings to operating system's API of
> threads, processes, signals and everything. It is simply not possible
> to cover all cases with tasks. You as an author should stop extending
> it in some point and say "everything else is beyond the scope of
> Ur/Web, use FFI if tasks are not enough". And, in fact, you did it.
I can certainly see the appeal of that position, especially to me. ;)
> I think it is better to direct efforts into improvement of the FFI
> interface and urweb API because we will need them anyway. If I only
> had methods for
>
> 1) clone the context to use it with a new thread inside an FFI
> 2) call the url handler (I already know that `uw_begin' or
> `uw_get_app(ctx)->handle(ctx, uri)' may help me here)
>
I think I'm basically on board with this proposal, but there is it least
one potential complication that seems worth bringing up.
Any Ur/Web code may encounter a benign exception requiring transaction
restart. The canonical example is a serialization failure from
optimistic SQL concurrency. Your suggestions above don't make it clear
how transactions should be handled in general, including where to jump
back to when a transaction needs restarting.
For simplicity's sake, what do you think of implementing the following
two functions instead?
1) clone context but don't start a transaction for it (note that this
also opens a database connection, checks the schema, and creates
prepared statements!)
2) given a context and a URI, run the associated Ur/Web code in that
context in a new transaction associated only with this operation
> PS
> By the way, I am missing the ability to pass Ur/Web records to/from
> FFI. Is it hard to implement? I imagine they are represented with a
> plain C structures in the transaction's memory pool so may it be that
> it is not that hard?
>
C struct "subtyping" works nominally: two identically defined structs
with different names are considered different types. Thus, one job of
the Ur/Web compiler is to group together all uses of structurally
equivalent record types, defining one C struct for each.
Because of this, it's hard to support _elegant_ use of Ur/Web records in
C FFI code. You should be safe redefining the struct type with a
different name and casting as necessary, though. This would require
some changes to the Ur/Web compiler to allow things that it currently
thinks are scary.
My main recommendation, though, is to do like this for a record that
needs to cross the Ur-C boundary. This would be code in an FFI .urs file:
type myrecord
val myrecord : int -> string -> myrecord
val getInt : myrecord -> int
val getString : myrecord -> string
More information about the Ur
mailing list