[MLton] Callback functions: how?

Matthew Fluet 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:
>> local
>>   datatype secret = SECRET
>> in
>>   fun register f = fns := (fn (SECRET, x) => f x) :: !fns
>> end
> 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 mailing list