#How to call different function if Fn item is a function pointer?

13 messages · Page 1 of 1 (latest)

gray mica
#

I currently have an API that accepts Fn items. I am able to do interesting optimizations where the F in F: Fn() is a function pointer in FFI land.

Partial list of optimizations I can do with function pointers:

  • No special drop handling.
  • No vtable lookups.
  • No heap allocation to store the Fn item. (currently required to box them for safety because reasons)
  • 2 pointer indirections instead of 3.
  • Not really important but less overall space used since an fn pointer is smaller than a Box<dyn Fn()>

How can I go about this without exposing different API's for function pointers and Fn items?

covert rover
#

No dynamic dispatch.
Hm? Calling a function pointer is by definition dynamic dispatch

gray mica
#

You are right, what I meant was no vtable lookups. I am not really familiar with the terminology. 😛

#

Nor with how dyn exactly works.

covert rover
#

I mean you could just have an enum

gray mica
#

Yes, but the problem there is it becomes something I expose in user code because I can't have some trait or generic that specializes for function pointers.
The closest I got was introducing a struct with methods and a From<F> for T where: F: Fn() where the methods specialize for fn and Fn. This didn't work as I was unable to express the lifetime of a struct argument using HRTB. The idea was a user would call a function that had a Into<T> so it would be them just passing a closure, but also allow them to specifically initialize from a function pointer via the method if they wanted to.

Said method looked like:

// 'a + Arg ofcourse doesn't work
fn from_fn_ptr<Arg, Ret>(f: for <'a> fn('a + Arg) -> Ret) -> Self {}
fn from_fn(...) -> Self {}

Problem here is that I can't specify the lifetime of Arg where the actual struct would be defined such as struct MyStruct<'a>(PhantomData<&'a ()>).
I can't pass a reference either as some of the fields can be taken or mutated.

#

For some context the Self above actually just contains a key to our value stored in C so the size and alignment is always same.

#

I was intentionally avoiding going in depth on the exact problem as its pretty complicated and instead boiled it down to a simple question that would solve my problem.

#

I have seen another library interacting with the same C library also encounter this and they seem to also just box everything.

spice totem
#

With feature(ptr_metadata), you can detect ZSTs and store only the vtable pointer (vtable lookup means nothing here, even less important than the two words of space), but this is totally overkill - if you are in an environment where dynamic linking exists, it is safe to assume that allocations are things you can do millions of times a second

gray mica
#

I guess there isn't much I can do 😦

Thanks for the help both of you. 🙂

regal herald