lib/finalize.rb
DEFINITIONS
This source file includes following functions.
1 #
2 # finalizer.rb -
3 # $Release Version: 0.3$
4 # $Revision: 1.4 $
5 # $Date: 1998/02/27 05:34:33 $
6 # by Keiju ISHITSUKA
7 #
8 # --
9 #
10 # Usage:
11 #
12 # add(obj, dependant, method = :finalize, *opt)
13 # add_dependency(obj, dependant, method = :finalize, *opt)
14 # add dependency R_method(obj, dependant)
15 #
16 # delete(obj_or_id, dependant, method = :finalize)
17 # delete_dependency(obj_or_id, dependant, method = :finalize)
18 # delete dependency R_method(obj, dependant)
19 # delete_all_dependency(obj_or_id, dependant)
20 # delete dependency R_*(obj, dependant)
21 # delete_by_dependant(dependant, method = :finalize)
22 # delete dependency R_method(*, dependant)
23 # delete_all_by_dependant(dependant)
24 # delete dependency R_*(*, dependant)
25 # delete_all
26 # delete all dependency R_*(*, *)
27 #
28 # finalize(obj_or_id, dependant, method = :finalize)
29 # finalize_dependency(obj_or_id, dependant, method = :finalize)
30 # finalize the dependant connected by dependency R_method(obj, dependtant).
31 # finalize_all_dependency(obj_or_id, dependant)
32 # finalize all dependants connected by dependency R_*(obj, dependtant).
33 # finalize_by_dependant(dependant, method = :finalize)
34 # finalize the dependant connected by dependency R_method(*, dependtant).
35 # finalize_all_by_dependant(dependant)
36 # finalize all dependants connected by dependency R_*(*, dependant).
37 # finalize_all
38 # finalize all dependency registered to the Finalizer.
39 #
40 # safe{..}
41 # stop invoking Finalizer on GC.
42 #
43
44 module Finalizer
45 RCS_ID='-$Id: finalize.rb,v 1.4 1998/02/27 05:34:33 keiju Exp keiju $-'
46
47 class <<self
48 # @dependency: {id => [[dependant, method, *opt], ...], ...}
49
50 # add dependency R_method(obj, dependant)
51 def add_dependency(obj, dependant, method = :finalize, *opt)
52 ObjectSpace.call_finalizer(obj)
53 method = method.intern unless method.kind_of?(Integer)
54 assoc = [dependant, method].concat(opt)
55 if dep = @dependency[obj.id]
56 dep.push assoc
57 else
58 @dependency[obj.id] = [assoc]
59 end
60 end
61 alias add add_dependency
62
63 # delete dependency R_method(obj, dependant)
64 def delete_dependency(id, dependant, method = :finalize)
65 id = id.id unless id.kind_of?(Integer)
66 method = method.intern unless method.kind_of?(Integer)
67 for assoc in @dependency[id]
68 assoc.delete_if do
69 |d, m, *o|
70 d == dependant && m == method
71 end
72 @dependency.delete(id) if assoc.empty?
73 end
74 end
75 alias delete delete_dependency
76
77 # delete dependency R_*(obj, dependant)
78 def delete_all_dependency(id, dependant)
79 id = id.id unless id.kind_of?(Integer)
80 method = method.intern unless method.kind_of?(Integer)
81 for assoc in @dependency[id]
82 assoc.delete_if do
83 |d, m, *o|
84 d == dependant
85 end
86 @dependency.delete(id) if assoc.empty?
87 end
88 end
89
90 # delete dependency R_method(*, dependant)
91 def delete_by_dependant(dependant, method = :finalize)
92 method = method.intern unless method.kind_of?(Integer)
93 for id in @dependency.keys
94 delete(id, dependant, method)
95 end
96 end
97
98 # delete dependency R_*(*, dependant)
99 def delete_all_by_dependant(dependant)
100 for id in @dependency.keys
101 delete_all_dependency(id, dependant)
102 end
103 end
104
105 # finalize the depandant connected by dependency R_method(obj, dependtant)
106 def finalize_dependency(id, dependant, method = :finalize)
107 id = id.id unless id.kind_of?(Integer)
108 method = method.intern unless method.kind_of?(Integer)
109 for assocs in @dependency[id]
110 assocs.delete_if do
111 |d, m, *o|
112 d.send(m, id, *o) if ret = d == dependant && m == method
113 ret
114 end
115 @dependency.delete(id) if assoc.empty?
116 end
117 end
118 alias finalize finalize_dependency
119
120 # finalize all dependants connected by dependency R_*(obj, dependtant)
121 def finalize_all_dependency(id, dependant)
122 id = id.id unless id.kind_of?(Integer)
123 method = method.intern unless method.kind_of?(Integer)
124 for assoc in @dependency[id]
125 assoc.delete_if do
126 |d, m, *o|
127 d.send(m, id, *o) if ret = d == dependant
128 end
129 @dependency.delete(id) if assoc.empty?
130 end
131 end
132
133 # finalize the dependant connected by dependency R_method(*, dependtant)
134 def finalize_by_dependant(dependant, method = :finalize)
135 method = method.intern unless method.kind_of?(Integer)
136 for id in @dependency.keys
137 finalize(id, dependant, method)
138 end
139 end
140
141 # finalize all dependants connected by dependency R_*(*, dependtant)
142 def finalize_all_by_dependant(dependant)
143 for id in @dependency.keys
144 finalize_all_dependency(id, dependant)
145 end
146 end
147
148 # finalize all dependants registered to the Finalizer.
149 def finalize_all
150 for id, assocs in @dependency
151 for dependant, method, *opt in assocs
152 dependant.send(method, id, *opt)
153 end
154 assocs.clear
155 end
156 end
157
158 # method to call finalize_* safely.
159 def safe
160 old_status = Thread.critical
161 Thread.critical = true
162 ObjectSpace.remove_finalizer(@proc)
163 begin
164 yield
165 ensure
166 ObjectSpace.add_finalizer(@proc)
167 Thread.critical = old_status
168 end
169 end
170
171 private
172
173 # registering function to ObjectSpace#add_finalizer
174 def final_of(id)
175 if assocs = @dependency.delete(id)
176 for dependant, method, *opt in assocs
177 dependant.send(method, id, *opt)
178 end
179 end
180 end
181
182 end
183 @dependency = Hash.new
184 @proc = proc{|id| final_of(id)}
185 ObjectSpace.add_finalizer(@proc)
186 end