utilrb 1.3 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Manifest.txt +4 -1
- data/ext/weakref.cc +142 -0
- data/lib/utilrb/common.rb +1 -1
- data/lib/utilrb/weakref.rb +18 -0
- metadata +5 -2
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
@@ -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:
|
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:
|