free 0.1.2-i386-mswin32 → 0.2.0-i386-mswin32
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/HISTORY +8 -0
- data/README.md +25 -8
- data/Rakefile +0 -14
- data/ext/free/free.c +43 -8
- data/lib/1.8/free.so +0 -0
- data/lib/1.9/free.so +0 -0
- data/lib/free/version.rb +1 -1
- data/lib/free.rb +7 -2
- data/test/test.rb +29 -0
- metadata +3 -6
data/HISTORY
CHANGED
data/README.md
CHANGED
@@ -9,16 +9,17 @@ free provides the `Object#free` method enabling a user to garbage
|
|
9
9
|
collect an object on demand and free all its internal structures.
|
10
10
|
|
11
11
|
* Install the [gem](https://rubygems.org/gems/free)
|
12
|
-
* Read the [documentation](http://rdoc.info/github/banister/free/master/file/README.
|
12
|
+
* Read the [documentation](http://rdoc.info/github/banister/free/master/file/README.md)
|
13
13
|
* See the [source code](http://github.com/banister/free)
|
14
14
|
|
15
|
-
Example:
|
16
|
-
|
15
|
+
Example: Freeing a String
|
16
|
+
-------------------------
|
17
17
|
|
18
18
|
Let's free a String:
|
19
19
|
|
20
20
|
hello = "hello world"
|
21
21
|
id = hello.object_id
|
22
|
+
|
22
23
|
hello.free
|
23
24
|
|
24
25
|
# Note we go through the id as accessing the freed object directly
|
@@ -26,20 +27,36 @@ Let's free a String:
|
|
26
27
|
ObjectSpace._id2ref(id) #=> RangeError: _id2ref': 0x1c1a63c is recycled object
|
27
28
|
|
28
29
|
|
30
|
+
Example: Destructors
|
31
|
+
--------------------
|
32
|
+
|
33
|
+
Free also supports object destructors. If the `__destruct__` method is
|
34
|
+
implemented on the object being freed it will be called before freeing
|
35
|
+
takes place; and the return value of `free` will be the return value of `__destruct__`:
|
36
|
+
|
37
|
+
o = Object.new
|
38
|
+
def o.__destruct__
|
39
|
+
:killed
|
40
|
+
end
|
41
|
+
|
42
|
+
o.free #=> :killed
|
43
|
+
|
29
44
|
Features and limitations
|
30
45
|
-------------------------
|
31
46
|
|
32
47
|
### Features
|
33
48
|
|
34
|
-
* Can free any object (
|
35
|
-
|
36
|
-
*
|
49
|
+
* Can free any object (but be careful, see below)
|
50
|
+
* Works in both Ruby 1.8 and 1.9.
|
51
|
+
* Some protection from freeing critical objects and immediate values.
|
52
|
+
* Supports object destructors
|
37
53
|
|
38
54
|
### Limitations
|
39
55
|
|
40
56
|
* Beta software, beware.
|
41
|
-
*
|
42
|
-
|
57
|
+
* Supports MRI and YARV only.
|
58
|
+
* Not complete protection from freeing silly things, e.g core classes. Be sensible :)
|
59
|
+
* Can be dangerous - `free` will force garbage collection on an object even if references to it still exist. Trying to access an already freed object may result in unexpected behaviour or segfaults.
|
43
60
|
|
44
61
|
Contact
|
45
62
|
-------
|
data/Rakefile
CHANGED
@@ -1,12 +1,6 @@
|
|
1
1
|
dlext = Config::CONFIG['DLEXT']
|
2
2
|
direc = File.dirname(__FILE__)
|
3
3
|
|
4
|
-
begin
|
5
|
-
require 'bones'
|
6
|
-
rescue LoadError
|
7
|
-
abort '### Please install the "bones" gem ###'
|
8
|
-
end
|
9
|
-
|
10
4
|
PROJECT_NAME = "free"
|
11
5
|
|
12
6
|
require 'rake/clean'
|
@@ -18,14 +12,6 @@ CLEAN.include("ext/**/*.#{dlext}", "ext/**/*.log", "ext/**/*.o",
|
|
18
12
|
"ext/**/*~", "ext/**/*#*", "ext/**/*.obj", "**/*#*", "**/*#*.*",
|
19
13
|
"ext/**/*.def", "ext/**/*.pdb", "**/*_flymake*.*", "**/*_flymake")
|
20
14
|
|
21
|
-
Bones do
|
22
|
-
name 'free'
|
23
|
-
authors 'John Mair (banisterfiend)'
|
24
|
-
email 'jrmair@gmail.com'
|
25
|
-
url 'http://banisterfiend.wordpress.com'
|
26
|
-
ignore_file '.gitignore'
|
27
|
-
end
|
28
|
-
|
29
15
|
def apply_spec_defaults(s)
|
30
16
|
s.name = PROJECT_NAME
|
31
17
|
s.summary = "Force immediate garbage collection of an object."
|
data/ext/free/free.c
CHANGED
@@ -46,10 +46,6 @@ typedef struct RVALUE {
|
|
46
46
|
struct SCOPE scope;
|
47
47
|
#endif
|
48
48
|
} as;
|
49
|
-
#ifdef GC_DEBUG
|
50
|
-
const char *file;
|
51
|
-
int line;
|
52
|
-
#endif
|
53
49
|
} RVALUE;
|
54
50
|
|
55
51
|
#define RANY(o) ((RVALUE*)(o))
|
@@ -97,16 +93,55 @@ make_deferred(RVALUE *p)
|
|
97
93
|
|
98
94
|
VALUE object_free(VALUE obj)
|
99
95
|
{
|
100
|
-
|
101
|
-
|
96
|
+
ID id_destructor = rb_intern("__destruct__");
|
97
|
+
|
98
|
+
/* value returned by destructor */
|
99
|
+
VALUE destruct_value = Qnil;
|
100
|
+
|
101
|
+
/* prevent freeing of immediates */
|
102
|
+
switch (TYPE(obj)) {
|
102
103
|
case T_NIL:
|
103
104
|
case T_FIXNUM:
|
104
105
|
case T_TRUE:
|
105
106
|
case T_FALSE:
|
106
|
-
|
107
|
+
case T_SYMBOL:
|
108
|
+
rb_raise(rb_eTypeError, "obj_free() called for immediate value");
|
107
109
|
break;
|
108
110
|
}
|
109
111
|
|
112
|
+
/* prevent freeing of *some* critical objects */
|
113
|
+
if ((obj == rb_cObject) ||
|
114
|
+
(obj == rb_cClass) ||
|
115
|
+
(obj == rb_cModule) ||
|
116
|
+
(obj == rb_cSymbol) ||
|
117
|
+
(obj == rb_cFixnum) ||
|
118
|
+
(obj == rb_cFloat) ||
|
119
|
+
(obj == rb_cString) ||
|
120
|
+
(obj == rb_cRegexp) ||
|
121
|
+
(obj == rb_cInteger) ||
|
122
|
+
(obj == rb_cArray) ||
|
123
|
+
(obj == rb_cNilClass) ||
|
124
|
+
(obj == rb_cFalseClass) ||
|
125
|
+
(obj == rb_cTrueClass) ||
|
126
|
+
(obj == rb_cNumeric) ||
|
127
|
+
(obj == rb_cBignum) ||
|
128
|
+
(obj == rb_cStruct))
|
129
|
+
rb_raise(rb_eTypeError, "obj_free() called for critical object");
|
130
|
+
|
131
|
+
/* run destructor (if one is defined) */
|
132
|
+
if (rb_respond_to(obj, id_destructor))
|
133
|
+
destruct_value = rb_funcall(obj, id_destructor, 0);
|
134
|
+
|
135
|
+
#ifdef RUBY_19
|
136
|
+
switch (BUILTIN_TYPE(obj)) {
|
137
|
+
case T_NIL:
|
138
|
+
case T_FIXNUM:
|
139
|
+
case T_TRUE:
|
140
|
+
case T_FALSE:
|
141
|
+
rb_bug("obj_free() called for broken object");
|
142
|
+
break;
|
143
|
+
}
|
144
|
+
|
110
145
|
if (FL_TEST(obj, FL_EXIVAR)) {
|
111
146
|
rb_free_generic_ivar((VALUE)obj);
|
112
147
|
FL_UNSET(obj, FL_EXIVAR);
|
@@ -346,7 +381,7 @@ VALUE object_free(VALUE obj)
|
|
346
381
|
|
347
382
|
rb_gc_force_recycle(obj);
|
348
383
|
|
349
|
-
return
|
384
|
+
return destruct_value;
|
350
385
|
}
|
351
386
|
|
352
387
|
void
|
data/lib/1.8/free.so
CHANGED
Binary file
|
data/lib/1.9/free.so
CHANGED
Binary file
|
data/lib/free/version.rb
CHANGED
data/lib/free.rb
CHANGED
@@ -9,10 +9,15 @@ require "#{direc}/free/version"
|
|
9
9
|
module Free
|
10
10
|
|
11
11
|
# Force garbage collection on an object and free its internal structures.
|
12
|
-
# @return nil
|
12
|
+
# @return [nil, Object] Return value of \_\_destruct\_\_ method (if
|
13
|
+
# defined) or nil (if no \_\_destruct\_\_ method)
|
13
14
|
# @example
|
14
15
|
# h = "hello"
|
15
|
-
# h.
|
16
|
+
# def h.__destruct__
|
17
|
+
# :killed
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# h.free #=> :killed
|
16
21
|
def free() end
|
17
22
|
end
|
18
23
|
|
data/test/test.rb
CHANGED
@@ -32,4 +32,33 @@ describe Free do
|
|
32
32
|
(ObjectSpace._id2ref(id) != v || lambda { ObjectSpace._id2ref(id) } rescue true).should == true
|
33
33
|
end
|
34
34
|
end
|
35
|
+
|
36
|
+
it 'should run destructor before freeing object' do
|
37
|
+
o = Object.new
|
38
|
+
|
39
|
+
def o.__destruct__
|
40
|
+
:killed
|
41
|
+
end
|
42
|
+
|
43
|
+
o.free.should == :killed
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should return nil if no destructor specified' do
|
47
|
+
o = Object.new
|
48
|
+
o.free.should == nil
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should raise when trying to free immediate values' do
|
52
|
+
[nil, 0, true, false, :symbol].each do |v|
|
53
|
+
lambda { v.free }.should.raise TypeError
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should raise when trying to free critical objects' do
|
58
|
+
[Object, Class, Module, Symbol, Fixnum, Float,
|
59
|
+
String, Regexp, Integer, Array, NilClass, FalseClass,
|
60
|
+
TrueClass, Numeric, Bignum, Struct].each do |v|
|
61
|
+
lambda { v.free }.should.raise TypeError
|
62
|
+
end
|
63
|
+
end
|
35
64
|
end
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: free
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 31
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
|
-
- 1
|
9
7
|
- 2
|
10
|
-
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
11
10
|
platform: i386-mswin32
|
12
11
|
authors:
|
13
12
|
- John Mair (banisterfiend)
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2011-01-
|
17
|
+
date: 2011-01-04 00:00:00 +13:00
|
19
18
|
default_executable:
|
20
19
|
dependencies: []
|
21
20
|
|
@@ -74,7 +73,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
74
73
|
requirements:
|
75
74
|
- - ">="
|
76
75
|
- !ruby/object:Gem::Version
|
77
|
-
hash: 3
|
78
76
|
segments:
|
79
77
|
- 0
|
80
78
|
version: "0"
|
@@ -83,7 +81,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
81
|
requirements:
|
84
82
|
- - ">="
|
85
83
|
- !ruby/object:Gem::Version
|
86
|
-
hash: 3
|
87
84
|
segments:
|
88
85
|
- 0
|
89
86
|
version: "0"
|