[MLton] Callback functions: how?
fluet at tti-c.org
Wed Feb 14 13:28:59 PST 2007
Wesley W. Terpstra wrote:
> On Feb 14, 2007, at 8:36 PM, Matthew Fluet wrote:
>> Wesley W. Terpstra wrote:
>>> As I understand it, the code
>>>> val fns : (int -> unit) list ref = ref [ fn _ => () ]
>>>> val register f = fns := f :: !fns
>>>> val runAll x = List.app (fn f => f x) (!fns)
>>> will prevent flow-analysis and the runAll method will have a loop
>>> over a giant switch statement that could call all possible functions
>>> of type 'int -> unit'. Is this correct? Or can MLton recognize that
>>> only methods passed to 'register' need to be in the switch statement?
>> I believe that MLton does something in between the two. That is,
>> flow-analysis is (purposefully) conservative on functions that escape
>> into mutable objects, but it does distinguish between escaping and
>> non-escaping functions. So, you won't get a dispatch among all
>> possible functions of type 'int -> unit'. On the other hand, if you
>> had 'register1' and 'register2' that added to different refs, then you
>> would get a dispatch among the set of functions passed to either
>> 'register1' or 'register2'.
> To help MLton out, I could create a locally defined type and add it to
> the callbacks input. eg:
>> datatype secret = SECRET
>> fun register f = fns := (fn (SECRET, x) => f x) :: !fns
> Would this be enough to ensure that it caught exactly the right methods?
I cooked up a little example, and this technique did separate out the
functions passed to the two different registers.
>> To complicate matters, some C callbacks don't give you a void* to hang
>> callback specific data; I think John Reppy has mentioned that some
>> OpenGL bindings are of that form. For that, we'd like to eventually
>> support an "indirect export" mechanism:
>> _export * : (int -> unit) -> MLton.Pointer.t;
> I remember we talked about this before. However, I wonder if it's truly
> necessary. If there is no user argument, the library probably intends
> for you to hook exactly one function. In which case, you can use the
> _export*_address trick explicitly for the one function. A single ref
> cell will hold the SML method to call. Easy.
Maybe; I know John had some example that would be a lot more elegant
with this mechanism.
More information about the MLton