Skip to content

Commit 15a335f

Browse files
authored
Merge pull request #141 from mrkn/use_weak_map
Use WeakMap for WrapperObjectCache
2 parents eeaf222 + d2bda9c commit 15a335f

File tree

1 file changed

+49
-25
lines changed

1 file changed

+49
-25
lines changed

lib/pycall/wrapper_object_cache.rb

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,47 @@
11
module PyCall
22
class WrapperObjectCache
3+
4+
begin
5+
ObjectSpace::WeakMap.new[42] = Object.new
6+
rescue
7+
WMAP_SUPPORT_INT_KEY = false
8+
else
9+
WMAP_SUPPORT_INT_KEY = true
10+
end
11+
12+
if WMAP_SUPPORT_INT_KEY
13+
def self.get_key(pyptr)
14+
pyptr.__address__
15+
end
16+
else
17+
class Key
18+
@address_key_map = {}
19+
20+
def self.[](address)
21+
@address_key_map[address] ||= new(address)
22+
end
23+
24+
def initialize(address)
25+
@address = address
26+
end
27+
28+
attr_reader :address
29+
30+
def ==(other)
31+
case other
32+
when Key
33+
self.address == other.address
34+
else
35+
super
36+
end
37+
end
38+
end
39+
40+
def self.get_key(pyptr)
41+
Key[pyptr.__address__]
42+
end
43+
end
44+
345
def initialize(*restricted_pytypes)
446
unless restricted_pytypes.empty?
547
restricted_pytypes.each do |pytype|
@@ -8,9 +50,7 @@ def initialize(*restricted_pytypes)
850
end
951
end
1052
@restricted_pytypes = restricted_pytypes
11-
@wrapper_object_table = {}
12-
@wrapped_pyptr_table = {}
13-
@weakref_table = {}
53+
@wrapper_object_table = ObjectSpace::WeakMap.new
1454
end
1555

1656
def lookup(pyptr)
@@ -25,16 +65,14 @@ def lookup(pyptr)
2565
end
2666
end
2767

28-
wrapper_object_id = @wrapper_object_table[pyptr.__address__]
29-
if wrapper_object_id
30-
wrapper_object = ObjectSpace._id2ref(wrapper_object_id) rescue nil
31-
return wrapper_object if wrapper_object
68+
key = self.class.get_key(pyptr)
69+
wrapper_object = @wrapper_object_table[key]
70+
unless wrapper_object
71+
wrapper_object = yield(pyptr)
72+
check_wrapper_object(wrapper_object)
73+
@wrapper_object_table[key] = wrapper_object
3274
end
3375

34-
wrapper_object = yield(pyptr)
35-
check_wrapper_object(wrapper_object)
36-
register_wrapper_object(pyptr, wrapper_object)
37-
3876
wrapper_object
3977
end
4078

@@ -43,19 +81,5 @@ def check_wrapper_object(wrapper_object)
4381
raise TypeError, "unexpected wrapper object (expected an object extended by PyObjectWrapper)"
4482
end
4583
end
46-
47-
def register_wrapper_object(pyptr, wrapper_object)
48-
@wrapper_object_table[pyptr.__address__] = wrapper_object.__id__
49-
@wrapped_pyptr_table[wrapper_object.__id__] = pyptr.__address__
50-
ObjectSpace.define_finalizer(wrapper_object, &method(:unregister_wrapper_object))
51-
# TODO: weakref
52-
self
53-
end
54-
55-
def unregister_wrapper_object(wrapper_object_id)
56-
pyptr_addr = @wrapped_pyptr_table.delete(wrapper_object_id)
57-
@wrapper_object_table.delete(pyptr_addr) if pyptr_addr
58-
self
59-
end
6084
end
6185
end

0 commit comments

Comments
 (0)