Class: Hakuban::FFIObject

Inherits:
Object
  • Object
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_dropObject



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

#dropObject



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 {
		#TODO: wait here till dropped?
		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

Returns:

  • (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

#inspectObject



126
127
128
# File 'lib/hakuban/ffi-object.rb', line 126

def inspect
	"#<#{self.class.name} #{self.dropped? ? "DROPPED" : "%016X"%@pointer}>"
end

#with_pointerObject



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