utilrb 1.3 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest.txt CHANGED
@@ -6,11 +6,12 @@ Rakefile
6
6
  bm/allocation.rb
7
7
  bm/speed.rb
8
8
  ext/extconf.rb
9
- ext/utilrb_ext.cc
10
9
  ext/ruby_internals-1.8.h
11
10
  ext/ruby_internals-1.9.h
12
11
  ext/swap.cc
12
+ ext/utilrb_ext.cc
13
13
  ext/value_set.cc
14
+ ext/weakref.cc
14
15
  lib/utilrb.rb
15
16
  lib/utilrb/array.rb
16
17
  lib/utilrb/array/to_s.rb
@@ -65,6 +66,7 @@ lib/utilrb/time/to_hms.rb
65
66
  lib/utilrb/unbound_method.rb
66
67
  lib/utilrb/unbound_method/call.rb
67
68
  lib/utilrb/value_set.rb
69
+ lib/utilrb/weakref.rb
68
70
  patches/gc_live_objects.patch
69
71
  test/data/test_pkgconfig.pc
70
72
  test/test_array.rb
@@ -84,3 +86,4 @@ test/test_proc.rb
84
86
  test/test_set.rb
85
87
  test/test_time.rb
86
88
  test/test_unbound_method.rb
89
+ test/test_weakref.rb
data/ext/weakref.cc ADDED
@@ -0,0 +1,142 @@
1
+ #include <set>
2
+ #include <map>
3
+ #include <ruby.h>
4
+ #include <intern.h>
5
+
6
+ using std::set;
7
+ using std::map;
8
+
9
+ static VALUE cWeakRef;
10
+ static VALUE cRefError;
11
+
12
+ /* Weakref internal structure. +obj+ is Qnil before initialization and Qundef
13
+ * after finalization */
14
+ struct WeakRef {
15
+ VALUE obj;
16
+ };
17
+
18
+ // Map from real objects to the set of associated WeakRef objects
19
+ typedef set<VALUE> ObjSet;
20
+ typedef map< VALUE, ObjSet > RefFromObjID;
21
+ typedef map< VALUE, VALUE > ObjFromRefID;
22
+ RefFromObjID from_obj_id;
23
+ ObjFromRefID from_ref_id;
24
+
25
+ static void weakref_free(WeakRef const* set) { delete set; }
26
+ static VALUE weakref_alloc(VALUE klass)
27
+ {
28
+ WeakRef* ref = new WeakRef;
29
+ ref->obj = Qnil;
30
+ return Data_Wrap_Struct(klass, NULL, weakref_free, ref);
31
+ }
32
+
33
+ static WeakRef& get_weakref(VALUE self)
34
+ {
35
+ WeakRef* object = 0;
36
+ Data_Get_Struct(self, WeakRef, object);
37
+ return *object;
38
+ }
39
+
40
+ static VALUE do_object_finalize(VALUE mod, VALUE obj_id)
41
+ {
42
+ RefFromObjID::iterator ref_set = from_obj_id.find(obj_id);
43
+ if (ref_set != from_obj_id.end())
44
+ {
45
+ ObjSet::iterator it = ref_set->second.begin();
46
+ ObjSet::iterator const end = ref_set->second.end();
47
+ for (; it != end; ++it)
48
+ {
49
+ /* During GC, objects are garbage collected and *then* the finalizers are called. It means that, even though *it is referenced in from_obj_id, it may be invalid.
50
+ *
51
+ * When an object is marked for deferred finalization, its flags
52
+ * are reset to a special value (flags = FL_MARK). FL_FINALIZE
53
+ * should therefore not be set on it anymore.
54
+ */
55
+ if (FL_TEST(*it, FL_FINALIZE))
56
+ {
57
+ WeakRef& ref = get_weakref(*it);
58
+ ref.obj = Qundef;
59
+ }
60
+ from_ref_id.erase(rb_obj_id(*it));
61
+ }
62
+
63
+ from_obj_id.erase(obj_id);
64
+ }
65
+ return Qnil;
66
+ }
67
+
68
+ static VALUE do_weakref_finalize(VALUE mod, VALUE ref_id)
69
+ {
70
+ ObjFromRefID::iterator obj_it = from_ref_id.find(ref_id);
71
+ if (obj_it != from_ref_id.end())
72
+ {
73
+ VALUE obj_id = rb_obj_id(obj_it->second);
74
+ RefFromObjID::iterator ref_set = from_obj_id.find(obj_id);
75
+ ref_set->second.erase(ref_id & ~FIXNUM_FLAG);
76
+ from_ref_id.erase(obj_it);
77
+ }
78
+ return Qnil;
79
+ }
80
+
81
+ // Note: the Ruby code has already registered +do_object_finalize+ as the
82
+ // finalizer for +obj+, and +do_weakref_finalize+ for +self+.
83
+ //
84
+ // It is forbidden to make a weakref-of-weakref or a weakref of an immediate
85
+ // object
86
+ static VALUE weakref_do_initialize(VALUE self, VALUE obj)
87
+ {
88
+ if (!FL_ABLE(obj))
89
+ {
90
+ VALUE str = rb_any_to_s(obj);
91
+ rb_raise(rb_eArgError, "%s cannot be finalized", StringValuePtr(str));
92
+ }
93
+
94
+ WeakRef& ref = get_weakref(self);
95
+ ref.obj = obj;
96
+
97
+ RefFromObjID::iterator it = from_obj_id.find(rb_obj_id(obj));
98
+ if (it == from_obj_id.end())
99
+ it = from_obj_id.insert( make_pair(rb_obj_id(obj), ObjSet()) ).first;
100
+
101
+ it->second.insert(self);
102
+ from_ref_id.insert( std::make_pair(rb_obj_id(self), obj) );
103
+
104
+ return Qnil;
105
+ }
106
+
107
+ static VALUE weakref_get(VALUE self)
108
+ {
109
+ WeakRef const& ref = get_weakref(self);
110
+
111
+ if (ref.obj == Qnil)
112
+ rb_raise(cRefError, "initialized weakref");
113
+ if (ref.obj == Qundef)
114
+ rb_raise(cRefError, "finalized object");
115
+ return ref.obj;
116
+ }
117
+
118
+ static VALUE refcount(VALUE mod, VALUE obj)
119
+ {
120
+ if (0 == obj & FIXNUM_FLAG)
121
+ obj = rb_obj_id(obj);
122
+
123
+ RefFromObjID::const_iterator it = from_obj_id.find(obj);
124
+ if (it == from_obj_id.end())
125
+ return Qnil;
126
+ else
127
+ return INT2FIX(it->second.size());
128
+ }
129
+
130
+ extern "C" void Init_weakref(VALUE mUtilrb)
131
+ {
132
+ cWeakRef = rb_define_class_under(mUtilrb, "WeakRef", rb_cObject);
133
+ cRefError = rb_define_class_under(cWeakRef, "RefError", rb_eStandardError);
134
+ rb_define_alloc_func(cWeakRef, weakref_alloc);
135
+
136
+ rb_define_singleton_method(cWeakRef, "do_object_finalize", RUBY_METHOD_FUNC(do_object_finalize), 1);
137
+ rb_define_singleton_method(cWeakRef, "do_weakref_finalize", RUBY_METHOD_FUNC(do_weakref_finalize), 1);
138
+ rb_define_singleton_method(cWeakRef, "refcount", RUBY_METHOD_FUNC(refcount), 1);
139
+ rb_define_method(cWeakRef, "do_initialize", RUBY_METHOD_FUNC(weakref_do_initialize), 1);
140
+ rb_define_method(cWeakRef, "get", RUBY_METHOD_FUNC(weakref_get), 0);
141
+ }
142
+
data/lib/utilrb/common.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Utilrb
2
2
  unless defined? Utilrb::VERSION
3
- VERSION = "1.3"
3
+ VERSION = "1.3.1"
4
4
  RUBY_IS_19 = (RUBY_VERSION >= "1.9")
5
5
  end
6
6
 
@@ -0,0 +1,18 @@
1
+ require 'utilrb/common'
2
+
3
+ Utilrb.require_ext("Utilrb::WeakRef") do
4
+ module Utilrb
5
+ class WeakRef
6
+ def initialize(obj)
7
+ if obj.kind_of?(WeakRef)
8
+ raise ArgumentError, "cannot create a weakref of a weakref"
9
+ end
10
+
11
+ ObjectSpace.define_finalizer(obj, self.class.method(:do_object_finalize))
12
+ ObjectSpace.define_finalizer(self, self.class.method(:do_weakref_finalize))
13
+ do_initialize(obj)
14
+ end
15
+ end
16
+ end
17
+ end
18
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: utilrb
3
3
  version: !ruby/object:Gem::Version
4
- version: "1.3"
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sylvain Joyeux
@@ -60,11 +60,12 @@ files:
60
60
  - bm/allocation.rb
61
61
  - bm/speed.rb
62
62
  - ext/extconf.rb
63
- - ext/utilrb_ext.cc
64
63
  - ext/ruby_internals-1.8.h
65
64
  - ext/ruby_internals-1.9.h
66
65
  - ext/swap.cc
66
+ - ext/utilrb_ext.cc
67
67
  - ext/value_set.cc
68
+ - ext/weakref.cc
68
69
  - lib/utilrb.rb
69
70
  - lib/utilrb/array.rb
70
71
  - lib/utilrb/array/to_s.rb
@@ -119,6 +120,7 @@ files:
119
120
  - lib/utilrb/unbound_method.rb
120
121
  - lib/utilrb/unbound_method/call.rb
121
122
  - lib/utilrb/value_set.rb
123
+ - lib/utilrb/weakref.rb
122
124
  - patches/gc_live_objects.patch
123
125
  - test/data/test_pkgconfig.pc
124
126
  - test/test_array.rb
@@ -138,6 +140,7 @@ files:
138
140
  - test/test_set.rb
139
141
  - test/test_time.rb
140
142
  - test/test_unbound_method.rb
143
+ - test/test_weakref.rb
141
144
  has_rdoc: true
142
145
  homepage: " http://utilrb.rubyforge.org"
143
146
  post_install_message: