Class: Hakuban::FFIObject
- Inherits:
-
Object
- Object
- Hakuban::FFIObject
show all
- Defined in:
- lib/hakuban/ffi-object.rb
Defined Under Namespace
Classes: PointerAlreadyDropped
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
Returns a new instance of FFIObject.
10
11
12
|
# File 'lib/hakuban/ffi-object.rb', line 10
def initialize
@pointer_mutex = Mutex.new
end
|
Class Method Details
.from_ffi_pointer(cls, pointer) ⇒ Object
20
21
22
|
# File 'lib/hakuban/ffi-object.rb', line 20
def self.from_ffi_pointer(cls, pointer)
cls.allocate.tap { |new_instance| new_instance.initialize_from_ffi_pointer(pointer) }
end
|
.generate_finalizer(symbol, pointer_address) ⇒ Object
95
96
97
98
99
|
# File 'lib/hakuban/ffi-object.rb', line 95
def self.generate_finalizer(symbol, pointer_address)
proc { |_|
FFI::method(symbol).call(::FFI::Pointer.new(pointer_address))
}
end
|
.with_pointers(objects, &original_block) ⇒ Object
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
# File 'lib/hakuban/ffi-object.rb', line 61
def self.with_pointers(objects,&original_block)
do_locked = proc { |original_block, remaining_objects, pointers|
if remaining_objects.size == 0
original_block.call(pointers)
else
object, i = remaining_objects.shift
object.with_pointer { |pointer|
pointers[i] = pointer
do_locked.call(original_block, remaining_objects, pointers)
}
end
}
do_locked.call(original_block, objects.each.with_index.sort_by { |object, i| object.instance_variable_get(:@pointer) || -i }, Array.new(objects.size))
end
|
Instance Method Details
#do_and_drop_or_return(&block) ⇒ Object
this should always be called with interrupts disabled, in the same section where pointer creation occurs
103
104
105
106
107
108
109
110
111
112
113
114
115
|
# File 'lib/hakuban/ffi-object.rb', line 103
def do_and_drop_or_return(&block)
if block
begin
Thread.handle_interrupt(Object => :immediate) {
yield self
}
ensure
self.drop
end
else
self
end
end
|
#drop ⇒ Object
77
78
79
80
81
82
83
84
85
86
87
|
# File 'lib/hakuban/ffi-object.rb', line 77
def drop
@pointer_mutex.synchronize {
Thread.handle_interrupt(Object => :never) {
if !!@pointer
ObjectSpace.undefine_finalizer(self)
FFI::method(@drop_fn).call(::FFI::Pointer.new(@pointer))
@pointer = nil
end
}
}
end
|
#dropped? ⇒ Boolean
90
91
92
|
# File 'lib/hakuban/ffi-object.rb', line 90
def dropped?
!@pointer
end
|
#initialize_copy(original) ⇒ Object
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
# File 'lib/hakuban/ffi-object.rb', line 30
def initialize_copy(original)
Thread.handle_interrupt(Object => :never) {
if @clone_fn.nil?
@pointer_mutex.synchronize {
raise PointerAlreadyDropped if original.instance_variable_get(:@pointer).nil?
original.instance_variable_set(:@pointer, nil)
ObjectSpace.undefine_finalizer(original)
}
else
original.with_pointer { |pointer|
@pointer = FFI::method(@clone_fn).call(::FFI::Pointer.new(pointer)).address
}
end
@pointer_mutex = Mutex.new
ObjectSpace.undefine_finalizer(self)
ObjectSpace.define_finalizer(self, FFIObject::generate_finalizer(@drop_fn, @pointer))
}
end
|
#inspect ⇒ Object
117
118
119
|
# File 'lib/hakuban/ffi-object.rb', line 117
def inspect
"#<#{self.class.name} #{self.dropped? ? "DROPPED" : "%016X"%@pointer}>"
end
|
#with_pointer ⇒ Object
50
51
52
53
54
55
56
57
58
|
# File 'lib/hakuban/ffi-object.rb', line 50
def with_pointer
@pointer_mutex.synchronize {
if @pointer
yield ::FFI::Pointer.new(@pointer)
else
raise PointerAlreadyDropped
end
}
end
|