Subject:
Re: [ruby-ffi] Struct/ManagedStruct and GC behaviour
From:
Thomas E Enebo
Date:
12/21/09 5:32 PM
To:
ruby-ffi@googlegroups.com

On Mon, Dec 21, 2009 at 4:20 PM, Wayne Meissner <wmeissner@gmail.com> wrote:
> 2009/12/22 Thomas E Enebo <tom.enebo@gmail.com>:
>> I have been wondering about the Struct API myself.   It seems like it
>> should support a simple explicit memory management API ala:
>>
>> class MyFFIStruct < FFI::Struct ....
>>
>> MyFFIStruct.new do |struct_instance|
>>   some_ffi_call struct_instance
>>   # Do other stuff....
>> end
>> # I know the block has disposed of my allocated struct
>
> It does support this indirectly via MemoryPointer.new
> e.g.
>  MemoryPointer.new(MyFFIStruct.size) do |p|
>    s = MyFFIStruct.new(p)
>    some_ffi_call s
>    # do other stuff
>  end
>
> An alternative is to use FFI::Buffer as the backing memory - on JRuby,
> that is jvm-heap memory, which is copied in/out of a temporary native
> memory area (usually on the stack) when passed to a native function.
> For small structs, especially ones that are passed to a native
> function just once, this can be up to 10x faster than the alloc/free
> cycle of a MemoryPointer backed Struct.

Thanks for the additional info and the code snippet for explicit
management.  Personally, I think that an explicit API like this should
be the norm since there are no guarantees on when GC happens and in my
experience it is much longer than most people expect.   I think too
many people believe in magic and the only way to combat it is to make
the implicit stuff be more typing (or the explicit stuff less typing).
  I will probably make a class method in Struct which allows something
like:

MyFFStruct.create do |struct|
...
end

Under the covers it will do what you demonstrated above:

def self.create(&block)
    MemoryPointer.new(size) { |p| block.call new(p) }
end

Or something like this...

-Tom

-- blog: http://blog.enebo.com twitter: tom_enebo mail: tom.enebo@gmail.com