Class: Kafka::FFI::Opaque
- Inherits:
-
Object
- Object
- Kafka::FFI::Opaque
- Extended by:
- FFI::DataConverter
- Defined in:
- lib/kafka/ffi/opaque.rb
Overview
Opaque provides a safe mechanism for providing Ruby objects as opaque pointers.
Opaque pointers are used heavily in librdkafka to allow for passing references to application state into callbacks, configs, and other contexts. Ruby’s garbage collector cannot check for references held in external FFI memory and will garbage collect objects that are otherwise not referenced leading to a segmentation fault.
Opaque solves this by allocated a memory address which is used as a hash key to look up the Ruby object when needed. This keeps a reference to the object in Ruby so it is not garbage collected. This method allows for Ruby objects to be moved in memory during compaction (in Ruby 2.7+) compared to storing a referece to a Ruby object.
Instance Attribute Summary collapse
-
#pointer ⇒ Object
readonly
Returns the value of attribute pointer.
-
#value ⇒ Object
readonly
Returns the value of attribute value.
Class Method Summary collapse
- .from_native(value, _ctx) ⇒ Object
-
.register(opaque) ⇒ Object
Register the Opaque the registry, keeping a reference to it to avoid it being garbage collected.
-
.remove(opaque) ⇒ Object
Remove the Opaque from the registry, putting it back in contention for garbage collection.
-
.to_native(value, _ctx) ⇒ FFI::Pointer
Pointer referencing the Opauqe value.
Instance Method Summary collapse
-
#free ⇒ Object
Free releases the pointer back to the system and removes the Opaque from the registry.
-
#initialize(value) ⇒ Opaque
constructor
A new instance of Opaque.
Constructor Details
Instance Attribute Details
#pointer ⇒ Object (readonly)
Returns the value of attribute pointer.
66 67 68 |
# File 'lib/kafka/ffi/opaque.rb', line 66 def pointer @pointer end |
#value ⇒ Object (readonly)
Returns the value of attribute value.
65 66 67 |
# File 'lib/kafka/ffi/opaque.rb', line 65 def value @value end |
Class Method Details
.from_native(value, _ctx) ⇒ Object
56 57 58 59 60 61 62 |
# File 'lib/kafka/ffi/opaque.rb', line 56 def from_native(value, _ctx) if value.null? return nil end @registry.fetch(value.address, nil) end |
.register(opaque) ⇒ Object
Register the Opaque the registry, keeping a reference to it to avoid it being garbage collected. This will replace any existing Opaque with the same address.
32 33 34 |
# File 'lib/kafka/ffi/opaque.rb', line 32 def register(opaque) @registry[opaque.pointer.address] = opaque end |
.remove(opaque) ⇒ Object
Remove the Opaque from the registry, putting it back in contention for garbage collection.
40 41 42 |
# File 'lib/kafka/ffi/opaque.rb', line 40 def remove(opaque) @registry.delete(opaque.pointer.address) end |
.to_native(value, _ctx) ⇒ FFI::Pointer
Returns Pointer referencing the Opauqe value.
47 48 49 50 51 52 53 |
# File 'lib/kafka/ffi/opaque.rb', line 47 def to_native(value, _ctx) if value.nil? return ::FFI::Pointer::NULL end value.pointer end |
Instance Method Details
#free ⇒ Object
Free releases the pointer back to the system and removes the Opaque from the registry. free should only be called when the Opaque is no longer stored in librdkafka as it frees the backing pointer which could cause a segfault if still referenced.
79 80 81 82 83 84 85 |
# File 'lib/kafka/ffi/opaque.rb', line 79 def free Opaque.remove(self) @pointer.free @value = nil @pointer = nil end |