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
Class Method Details
.generate_finalizer(symbol, pointer_address) ⇒ Object
97
98
99
100
101
|
# File 'lib/hakuban/ffi-object.rb', line 97
def self.generate_finalizer(symbol, pointer_address)
proc { |_|
FFI::method(symbol).call(::FFI::Pointer.new(pointer_address))
}
end
|
.with_pointers(objects, &original_block) ⇒ Object
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
# File 'lib/hakuban/ffi-object.rb', line 43
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 ⇒ Object
104
105
106
107
108
109
110
111
112
113
114
|
# File 'lib/hakuban/ffi-object.rb', line 104
def do_and_drop
Thread.handle_interrupt(Object => :never) {
begin
Thread.handle_interrupt(Object => :immediate) {
yield self
}
ensure
self.drop
end
}
end
|
#do_and_drop_or_return(&block) ⇒ Object
117
118
119
120
121
122
123
|
# File 'lib/hakuban/ffi-object.rb', line 117
def do_and_drop_or_return(&block)
if block
do_and_drop(&block)
else
self
end
end
|
#drop ⇒ Object
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
# File 'lib/hakuban/ffi-object.rb', line 59
def drop
@mutex.synchronize {
return if @drop_requested
@drop_requested = true
@drop_locked_by.each { |queue| queue << :dropping }
@drop_locked_by_condvar ||= ConditionVariable.new
@drop_locked_by_condvar.wait(@mutex) while @drop_locked_by.size > 0
return if dropped?
ObjectSpace.undefine_finalizer(self)
FFI::method(@drop_fn).call(::FFI::Pointer.new(@pointer))
@pointer = @finalizer = nil
}
end
|
#drop_lock(queue) ⇒ Object
75
76
77
78
79
80
81
|
# File 'lib/hakuban/ffi-object.rb', line 75
def drop_lock(queue)
@mutex.synchronize {
raise FFIObject::PointerAlreadyDropped if @drop_requested
@drop_locked_by << queue
}
true
end
|
#drop_release(queue) ⇒ Object
84
85
86
87
88
89
|
# File 'lib/hakuban/ffi-object.rb', line 84
def drop_release(queue)
@mutex.synchronize {
@drop_locked_by.delete(queue)
@drop_locked_by_condvar.broadcast if @drop_locked_by_condvar
}
end
|
#dropped? ⇒ Boolean
92
93
94
|
# File 'lib/hakuban/ffi-object.rb', line 92
def dropped?
@pointer.nil?
end
|
#initialize_copy(original) ⇒ Object
20
21
22
23
24
25
26
27
28
29
30
31
32
|
# File 'lib/hakuban/ffi-object.rb', line 20
def initialize_copy(original)
raise "#{self.class.name} can't be cloned. Consider making a new one instead." if @clone_fn.nil?
@mutex.synchronize {
raise "#{self.class.name} can't be cloned after 'drop' has been called on it." if @pointer.nil?
@pointer = FFI::method(@clone_fn).call(::FFI::Pointer.new(@pointer)).address
@mutex = Mutex.new
@drop_requested = false
@drop_locked_by = Set.new
@drop_locked_by_condvar = nil
ObjectSpace.undefine_finalizer(self)
ObjectSpace.define_finalizer(self, FFIObject::generate_finalizer(@drop_fn, @pointer))
}
end
|
#inspect ⇒ Object
126
127
128
|
# File 'lib/hakuban/ffi-object.rb', line 126
def inspect
"#<#{self.class.name} #{self.dropped? ? "DROPPED" : "%016X"%@pointer}>"
end
|
#with_pointer ⇒ Object
35
36
37
38
39
40
|
# File 'lib/hakuban/ffi-object.rb', line 35
def with_pointer
@mutex.synchronize {
raise PointerAlreadyDropped if dropped?
yield ::FFI::Pointer.new(@pointer)
}
end
|