1
1
module PyCall
2
2
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
+
3
45
def initialize ( *restricted_pytypes )
4
46
unless restricted_pytypes . empty?
5
47
restricted_pytypes . each do |pytype |
@@ -8,9 +50,7 @@ def initialize(*restricted_pytypes)
8
50
end
9
51
end
10
52
@restricted_pytypes = restricted_pytypes
11
- @wrapper_object_table = { }
12
- @wrapped_pyptr_table = { }
13
- @weakref_table = { }
53
+ @wrapper_object_table = ObjectSpace ::WeakMap . new
14
54
end
15
55
16
56
def lookup ( pyptr )
@@ -25,16 +65,14 @@ def lookup(pyptr)
25
65
end
26
66
end
27
67
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
32
74
end
33
75
34
- wrapper_object = yield ( pyptr )
35
- check_wrapper_object ( wrapper_object )
36
- register_wrapper_object ( pyptr , wrapper_object )
37
-
38
76
wrapper_object
39
77
end
40
78
@@ -43,19 +81,5 @@ def check_wrapper_object(wrapper_object)
43
81
raise TypeError , "unexpected wrapper object (expected an object extended by PyObjectWrapper)"
44
82
end
45
83
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
60
84
end
61
85
end
0 commit comments