free 0.1.0-i386-mingw32

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY ADDED
File without changes
data/README.md ADDED
@@ -0,0 +1,79 @@
1
+ nfree
2
+ =====
3
+
4
+ (C) John Mair (banisterfiend) 2010
5
+
6
+ _force immediate garbage collection of Ruby objects_
7
+
8
+ free provides the `Object#free` method enabling a user to garbage
9
+ collect an object on demand and free all its internal structures.
10
+
11
+ * Install the [gem](https://rubygems.org/gems/free)
12
+ * Read the [documentation](http://rdoc.info/github/github/banister/free/master/file/README.markdown)
13
+ * See the [source code](http://github.com/banister/free)
14
+
15
+ Example:
16
+ --------
17
+
18
+ Let's free a String:
19
+
20
+ hello = "hello world"
21
+ id = hello.object_id
22
+ hello.free
23
+
24
+ # Note we go through the id as accessing the freed object directly
25
+ # may cause a segfault
26
+ ObjectSpace._id2ref(id) #=> RangeError: _id2ref': 0x1c1a63c is recycled object
27
+
28
+
29
+ Features and limitations
30
+ -------------------------
31
+
32
+ ### Features
33
+
34
+ * Can free any object (except immediate values, that do not need
35
+ freeing)
36
+ * Works in both Ruby 1.8 and 1.9, MRI and YARV only.
37
+
38
+ ### Limitations
39
+
40
+ * Beta software, beware.
41
+ * Can be dangerous - `free` will force garbage collection on an object
42
+ even if references to it still exist. Trying to access an already freed object may result in unexpected behaviour or segfaults.
43
+
44
+ Contact
45
+ -------
46
+
47
+ Problems or questions contact me at [github](http://github.com/banister)
48
+
49
+ Special Thanks
50
+ --------------
51
+
52
+ [Coderrr](http://coderrr.wordpress.com) for the idea
53
+
54
+
55
+ License
56
+ -------
57
+
58
+ (The MIT License)
59
+
60
+ Copyright (c) 2011 (John Mair)
61
+
62
+ Permission is hereby granted, free of charge, to any person obtaining
63
+ a copy of this software and associated documentation files (the
64
+ 'Software'), to deal in the Software without restriction, including
65
+ without limitation the rights to use, copy, modify, merge, publish,
66
+ distribute, sublicense, and/or sell copies of the Software, and to
67
+ permit persons to whom the Software is furnished to do so, subject to
68
+ the following conditions:
69
+
70
+ The above copyright notice and this permission notice shall be
71
+ included in all copies or substantial portions of the Software.
72
+
73
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
74
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
75
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
76
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
77
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
78
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
79
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,114 @@
1
+ dlext = Config::CONFIG['DLEXT']
2
+ direc = File.dirname(__FILE__)
3
+
4
+ begin
5
+ require 'bones'
6
+ rescue LoadError
7
+ abort '### Please install the "bones" gem ###'
8
+ end
9
+
10
+ PROJECT_NAME = "free"
11
+
12
+ require 'rake/clean'
13
+ require 'rake/gempackagetask'
14
+ require "#{direc}/lib/#{PROJECT_NAME}/version"
15
+
16
+ CLOBBER.include("**/*.#{dlext}", "**/*~", "**/*#*", "**/*.log", "**/*.o")
17
+ CLEAN.include("ext/**/*.#{dlext}", "ext/**/*.log", "ext/**/*.o",
18
+ "ext/**/*~", "ext/**/*#*", "ext/**/*.obj", "**/*#*", "**/*#*.*",
19
+ "ext/**/*.def", "ext/**/*.pdb", "**/*_flymake*.*", "**/*_flymake")
20
+
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
+ def apply_spec_defaults(s)
30
+ s.name = PROJECT_NAME
31
+ s.summary = "Force immediate garbage collection of an object."
32
+ s.version = Free::VERSION
33
+ s.date = Time.now.strftime '%Y-%m-%d'
34
+ s.author = "John Mair (banisterfiend)"
35
+ s.email = 'jrmair@gmail.com'
36
+ s.description = s.summary
37
+ s.require_path = 'lib'
38
+ s.homepage = "http://banisterfiend.wordpress.com"
39
+ s.has_rdoc = 'yard'
40
+ s.files = Dir["ext/**/extconf.rb", "ext/**/*.h", "ext/**/*.c", "lib/**/*.rb",
41
+ "test/*.rb", "HISTORY", "README.md", "Rakefile"]
42
+ end
43
+
44
+ desc "run tests"
45
+ task :test do
46
+ sh "bacon -k #{direc}/test/test.rb"
47
+ end
48
+
49
+ [:mingw32, :mswin32].each do |v|
50
+ namespace v do
51
+ spec = Gem::Specification.new do |s|
52
+ apply_spec_defaults(s)
53
+ s.platform = "i386-#{v}"
54
+ s.files += FileList["lib/**/*.#{dlext}"].to_a
55
+ end
56
+
57
+ Rake::GemPackageTask.new(spec) do |pkg|
58
+ pkg.need_zip = false
59
+ pkg.need_tar = false
60
+ end
61
+ end
62
+ end
63
+
64
+ namespace :ruby do
65
+ spec = Gem::Specification.new do |s|
66
+ apply_spec_defaults(s)
67
+ s.platform = Gem::Platform::RUBY
68
+ s.extensions = ["ext/#{PROJECT_NAME}/extconf.rb"]
69
+ end
70
+
71
+ Rake::GemPackageTask.new(spec) do |pkg|
72
+ pkg.need_zip = false
73
+ pkg.need_tar = false
74
+ end
75
+ end
76
+
77
+ directories = ["#{direc}/lib/1.8", "#{direc}/lib/1.9"]
78
+ directories.each { |d| directory d }
79
+
80
+ desc "build the 1.8 and 1.9 binaries from source and copy to lib/"
81
+ task :compile => directories do
82
+ build_for = proc do |pik_ver, ver|
83
+ sh %{ \
84
+ c:\\devkit\\devkitvars.bat && \
85
+ pik #{pik_ver} && \
86
+ ruby extconf.rb && \
87
+ make clean && \
88
+ make && \
89
+ cp *.so #{direc}/lib/#{ver} \
90
+ }
91
+ end
92
+
93
+ chdir("#{direc}/ext/#{PROJECT_NAME}") do
94
+ build_for.call("187", "1.8")
95
+ build_for.call("192", "1.9")
96
+ end
97
+ end
98
+
99
+ desc "build all platform gems at once"
100
+ task :gems => [:clean, :rmgems, "mingw32:gem", "mswin32:gem", "ruby:gem"]
101
+
102
+ desc "remove all platform gems"
103
+ task :rmgems => ["ruby:clobber_package"]
104
+
105
+ desc "build and push latest gems"
106
+ task :pushgems => :gems do
107
+ chdir("#{direc}/pkg") do
108
+ Dir["*.gem"].each do |gemfile|
109
+ sh "gem push #{gemfile}"
110
+ end
111
+ end
112
+ end
113
+
114
+
data/ext/free/compat.h ADDED
@@ -0,0 +1,57 @@
1
+ /* contains basic macros to facilitate ruby 1.8 and ruby 1.9 compatibility */
2
+
3
+ #ifndef GUARD_COMPAT_H
4
+ #define GUARD_COMPAT_H
5
+
6
+ #include <ruby.h>
7
+
8
+ /* test for 1.9 */
9
+ #if !defined(RUBY_19) && defined(ROBJECT_EMBED_LEN_MAX)
10
+ # define RUBY_19
11
+ #endif
12
+
13
+ /* macros for backwards compatibility with 1.8 */
14
+ #ifndef RUBY_19
15
+ # define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
16
+ # define RCLASS_SUPER(c) (RCLASS(c)->super)
17
+ # define RCLASS_IV_TBL(c) (RCLASS(c)->iv_tbl)
18
+ # define OBJ_UNTRUSTED OBJ_TAINTED
19
+ # include "st.h"
20
+ #endif
21
+
22
+ #ifdef RUBY_19
23
+ inline static VALUE
24
+ class_alloc(VALUE flags, VALUE klass)
25
+ {
26
+ rb_classext_t *ext = ALLOC(rb_classext_t);
27
+ NEWOBJ(obj, struct RClass);
28
+ OBJSETUP(obj, klass, flags);
29
+ obj->ptr = ext;
30
+ RCLASS_IV_TBL(obj) = 0;
31
+ RCLASS_M_TBL(obj) = 0;
32
+ RCLASS_SUPER(obj) = 0;
33
+ RCLASS_IV_INDEX_TBL(obj) = 0;
34
+ return (VALUE)obj;
35
+ }
36
+ #endif
37
+
38
+ inline static VALUE
39
+ create_class(VALUE flags, VALUE klass)
40
+ {
41
+ #ifdef RUBY_19
42
+ VALUE new_klass = class_alloc(flags, klass);
43
+ #else
44
+ NEWOBJ(new_klass, struct RClass);
45
+ OBJSETUP(new_klass, klass, flags);
46
+ #endif
47
+
48
+ return (VALUE)new_klass;
49
+ }
50
+
51
+ # define FALSE 0
52
+ # define TRUE 1
53
+
54
+ /* a useful macro. cannot use ordinary CLASS_OF as it does not return an lvalue */
55
+ #define KLASS_OF(c) (RBASIC(c)->klass)
56
+
57
+ #endif
@@ -0,0 +1,5 @@
1
+ require 'mkmf'
2
+
3
+ $CFLAGS += " -std=c99"
4
+
5
+ create_makefile('free')
data/ext/free/free.c ADDED
@@ -0,0 +1,358 @@
1
+ /* (c) 2010 John Mair (banisterfiend), MIT license */
2
+
3
+ #include <ruby.h>
4
+ #include "compat.h"
5
+
6
+ #ifdef RUBY_19
7
+ # include <ruby/io.h>
8
+ # include <ruby/re.h>
9
+ # include <vm_core.h>
10
+ #else
11
+ # include "re.h"
12
+ # include "env.h"
13
+ # include "node.h"
14
+ # include "rubysig.h"
15
+ # include "rubyio.h"
16
+ #endif
17
+
18
+ #include "free.h"
19
+
20
+ typedef struct RVALUE {
21
+ union {
22
+ struct {
23
+ VALUE flags; /* always 0 for freed obj */
24
+ struct RVALUE *next;
25
+ } free;
26
+ struct RBasic basic;
27
+ struct RObject object;
28
+ struct RClass klass;
29
+ struct RFloat flonum;
30
+ struct RString string;
31
+ struct RArray array;
32
+ struct RRegexp regexp;
33
+ struct RHash hash;
34
+ struct RData data;
35
+ struct RStruct rstruct;
36
+ struct RBignum bignum;
37
+ struct RFile file;
38
+ struct RNode node;
39
+ struct RMatch match;
40
+ #ifdef RUBY_19
41
+ struct RTypedData typeddata;
42
+ struct RRational rational;
43
+ struct RComplex complex;
44
+ #else
45
+ struct RVarmap varmap;
46
+ struct SCOPE scope;
47
+ #endif
48
+ } as;
49
+ #ifdef GC_DEBUG
50
+ const char *file;
51
+ int line;
52
+ #endif
53
+ } RVALUE;
54
+
55
+ #define RANY(o) ((RVALUE*)(o))
56
+
57
+ #ifdef RUBY_19
58
+ static inline void
59
+ make_deferred(RVALUE *p)
60
+ {
61
+ p->as.basic.flags = (p->as.basic.flags & ~T_MASK) | T_ZOMBIE;
62
+ }
63
+
64
+ static inline void
65
+ make_io_deferred(RVALUE *p)
66
+ {
67
+ rb_io_t *fptr = p->as.file.fptr;
68
+ make_deferred(p);
69
+ p->as.data.dfree = (void (*)(void*))rb_io_fptr_finalize;
70
+ p->as.data.data = fptr;
71
+ }
72
+
73
+ static int
74
+ free_method_entry_i(ID key, rb_method_entry_t *me, st_data_t data)
75
+ {
76
+ rb_free_method_entry(me);
77
+ return ST_CONTINUE;
78
+ }
79
+
80
+ static void
81
+ rb_free_m_table(st_table *tbl)
82
+ {
83
+ st_foreach(tbl, free_method_entry_i, 0);
84
+ st_free_table(tbl);
85
+ }
86
+ #else
87
+
88
+ #define T_DEFERRED 0x3a
89
+
90
+ static inline void
91
+ make_deferred(RVALUE *p)
92
+ {
93
+ p->as.basic.flags = (p->as.basic.flags & ~T_MASK) | T_DEFERRED;
94
+ }
95
+
96
+ #endif
97
+
98
+ VALUE object_free(VALUE obj)
99
+ {
100
+ #ifdef RUBY_19
101
+ switch (BUILTIN_TYPE(obj)) {
102
+ case T_NIL:
103
+ case T_FIXNUM:
104
+ case T_TRUE:
105
+ case T_FALSE:
106
+ rb_bug("obj_free() called for broken object");
107
+ break;
108
+ }
109
+
110
+ if (FL_TEST(obj, FL_EXIVAR)) {
111
+ rb_free_generic_ivar((VALUE)obj);
112
+ FL_UNSET(obj, FL_EXIVAR);
113
+ }
114
+
115
+ switch (BUILTIN_TYPE(obj)) {
116
+ case T_OBJECT:
117
+ if (!(RANY(obj)->as.basic.flags & ROBJECT_EMBED) &&
118
+ RANY(obj)->as.object.as.heap.ivptr) {
119
+ xfree(RANY(obj)->as.object.as.heap.ivptr);
120
+ }
121
+ break;
122
+ case T_MODULE:
123
+ case T_CLASS:
124
+ rb_clear_cache_by_class((VALUE)obj);
125
+ rb_free_m_table(RCLASS_M_TBL(obj));
126
+ if (RCLASS_IV_TBL(obj)) {
127
+ st_free_table(RCLASS_IV_TBL(obj));
128
+ }
129
+ if (RCLASS_IV_INDEX_TBL(obj)) {
130
+ st_free_table(RCLASS_IV_INDEX_TBL(obj));
131
+ }
132
+ xfree(RANY(obj)->as.klass.ptr);
133
+ break;
134
+ case T_STRING:
135
+ rb_str_free(obj);
136
+ break;
137
+ case T_ARRAY:
138
+ rb_ary_free(obj);
139
+ break;
140
+ case T_HASH:
141
+ if (RANY(obj)->as.hash.ntbl) {
142
+ st_free_table(RANY(obj)->as.hash.ntbl);
143
+ }
144
+ break;
145
+ case T_REGEXP:
146
+ if (RANY(obj)->as.regexp.ptr) {
147
+ onig_free(RANY(obj)->as.regexp.ptr);
148
+ }
149
+ break;
150
+ case T_DATA:
151
+ if (DATA_PTR(obj)) {
152
+ if (RTYPEDDATA_P(obj)) {
153
+ RDATA(obj)->dfree = RANY(obj)->as.typeddata.type->dfree;
154
+ }
155
+ if ((long)RANY(obj)->as.data.dfree == -1) {
156
+ xfree(DATA_PTR(obj));
157
+ }
158
+ else if (RANY(obj)->as.data.dfree) {
159
+ make_deferred(RANY(obj));
160
+ return 1;
161
+ }
162
+ }
163
+ break;
164
+ case T_MATCH:
165
+ if (RANY(obj)->as.match.rmatch) {
166
+ struct rmatch *rm = RANY(obj)->as.match.rmatch;
167
+ onig_region_free(&rm->regs, 0);
168
+ if (rm->char_offset)
169
+ xfree(rm->char_offset);
170
+ xfree(rm);
171
+ }
172
+ break;
173
+ case T_FILE:
174
+ if (RANY(obj)->as.file.fptr) {
175
+ make_io_deferred(RANY(obj));
176
+ return 1;
177
+ }
178
+ break;
179
+ case T_RATIONAL:
180
+ case T_COMPLEX:
181
+ break;
182
+ case T_ICLASS:
183
+ /* iClass shares table with the module */
184
+ xfree(RANY(obj)->as.klass.ptr);
185
+ break;
186
+
187
+ case T_FLOAT:
188
+ break;
189
+
190
+ case T_BIGNUM:
191
+ if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) {
192
+ xfree(RBIGNUM_DIGITS(obj));
193
+ }
194
+ break;
195
+ case T_NODE:
196
+ switch (nd_type(obj)) {
197
+ case NODE_SCOPE:
198
+ if (RANY(obj)->as.node.u1.tbl) {
199
+ xfree(RANY(obj)->as.node.u1.tbl);
200
+ }
201
+ break;
202
+ case NODE_ALLOCA:
203
+ xfree(RANY(obj)->as.node.u1.node);
204
+ break;
205
+ }
206
+ break; /* no need to free iv_tbl */
207
+
208
+ case T_STRUCT:
209
+ if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 &&
210
+ RANY(obj)->as.rstruct.as.heap.ptr) {
211
+ xfree(RANY(obj)->as.rstruct.as.heap.ptr);
212
+ }
213
+ break;
214
+
215
+ default:
216
+ rb_bug("gc_sweep(): unknown data type 0x%x(%p)",
217
+ BUILTIN_TYPE(obj), (void*)obj);
218
+ }
219
+
220
+ #else
221
+ switch (BUILTIN_TYPE(obj)) {
222
+ case T_NIL:
223
+ case T_FIXNUM:
224
+ case T_TRUE:
225
+ case T_FALSE:
226
+ rb_bug("obj_free() called for broken object");
227
+ break;
228
+ }
229
+
230
+ if (FL_TEST(obj, FL_EXIVAR)) {
231
+ rb_free_generic_ivar((VALUE)obj);
232
+ }
233
+
234
+ switch (BUILTIN_TYPE(obj)) {
235
+ case T_OBJECT:
236
+ if (RANY(obj)->as.object.iv_tbl) {
237
+ st_free_table(RANY(obj)->as.object.iv_tbl);
238
+ }
239
+ break;
240
+ case T_MODULE:
241
+ case T_CLASS:
242
+ rb_clear_cache_by_class((VALUE)obj);
243
+ st_free_table(RANY(obj)->as.klass.m_tbl);
244
+ if (RANY(obj)->as.object.iv_tbl) {
245
+ st_free_table(RANY(obj)->as.object.iv_tbl);
246
+ }
247
+ break;
248
+ case T_STRING:
249
+ if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) {
250
+ RUBY_CRITICAL(free(RANY(obj)->as.string.ptr));
251
+ }
252
+ break;
253
+ case T_ARRAY:
254
+ if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) {
255
+ RUBY_CRITICAL(free(RANY(obj)->as.array.ptr));
256
+ }
257
+ break;
258
+ case T_HASH:
259
+ if (RANY(obj)->as.hash.tbl) {
260
+ st_free_table(RANY(obj)->as.hash.tbl);
261
+ }
262
+ break;
263
+ case T_REGEXP:
264
+ if (RANY(obj)->as.regexp.ptr) {
265
+ re_free_pattern(RANY(obj)->as.regexp.ptr);
266
+ }
267
+ if (RANY(obj)->as.regexp.str) {
268
+ RUBY_CRITICAL(free(RANY(obj)->as.regexp.str));
269
+ }
270
+ break;
271
+ case T_DATA:
272
+ if (DATA_PTR(obj)) {
273
+ if ((long)RANY(obj)->as.data.dfree == -1) {
274
+ RUBY_CRITICAL(free(DATA_PTR(obj)));
275
+ }
276
+ else if (RANY(obj)->as.data.dfree) {
277
+ make_deferred(RANY(obj));
278
+ return 1;
279
+ }
280
+ }
281
+ break;
282
+ case T_MATCH:
283
+ if (RANY(obj)->as.match.regs) {
284
+ re_free_registers(RANY(obj)->as.match.regs);
285
+ RUBY_CRITICAL(free(RANY(obj)->as.match.regs));
286
+ }
287
+ break;
288
+ case T_FILE:
289
+ if (RANY(obj)->as.file.fptr) {
290
+ struct rb_io_t *fptr = RANY(obj)->as.file.fptr;
291
+ make_deferred(RANY(obj));
292
+ RDATA(obj)->dfree = (void (*)(void*))rb_io_fptr_finalize;
293
+ RDATA(obj)->data = fptr;
294
+ return 1;
295
+ }
296
+ break;
297
+ case T_ICLASS:
298
+ /* iClass shares table with the module */
299
+ break;
300
+
301
+ case T_FLOAT:
302
+ case T_VARMAP:
303
+ case T_BLKTAG:
304
+ break;
305
+
306
+ case T_BIGNUM:
307
+ if (RANY(obj)->as.bignum.digits) {
308
+ RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits));
309
+ }
310
+ break;
311
+ case T_NODE:
312
+ switch (nd_type(obj)) {
313
+ case NODE_SCOPE:
314
+ if (RANY(obj)->as.node.u1.tbl) {
315
+ RUBY_CRITICAL(free(RANY(obj)->as.node.u1.tbl));
316
+ }
317
+ break;
318
+ case NODE_ALLOCA:
319
+ RUBY_CRITICAL(free(RANY(obj)->as.node.u1.node));
320
+ break;
321
+ }
322
+ break; /* no need to free iv_tbl */
323
+
324
+ case T_SCOPE:
325
+ if (RANY(obj)->as.scope.local_vars &&
326
+ RANY(obj)->as.scope.flags != SCOPE_ALLOCA) {
327
+ VALUE *vars = RANY(obj)->as.scope.local_vars-1;
328
+ if (!(RANY(obj)->as.scope.flags & SCOPE_CLONE) && vars[0] == 0)
329
+ RUBY_CRITICAL(free(RANY(obj)->as.scope.local_tbl));
330
+ if ((RANY(obj)->as.scope.flags & (SCOPE_MALLOC|SCOPE_CLONE)) == SCOPE_MALLOC)
331
+ RUBY_CRITICAL(free(vars));
332
+ }
333
+ break;
334
+
335
+ case T_STRUCT:
336
+ if (RANY(obj)->as.rstruct.ptr) {
337
+ RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr));
338
+ }
339
+ break;
340
+
341
+ default:
342
+ rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)",
343
+ RANY(obj)->as.basic.flags & T_MASK, obj);
344
+ }
345
+ #endif
346
+
347
+ rb_gc_force_recycle(obj);
348
+
349
+ return Qnil;
350
+ }
351
+
352
+ void
353
+ Init_free()
354
+ {
355
+ VALUE cFree = rb_define_module("Free");
356
+
357
+ rb_define_method(cFree, "free", object_free, 0);
358
+ }
data/ext/free/free.h ADDED
@@ -0,0 +1,6 @@
1
+ #ifndef GUARD_FREE_H
2
+ #define GUARD_FREE_H
3
+
4
+ VALUE rb_object_free(VALUE obj);
5
+
6
+ #endif
data/lib/1.8/free.so ADDED
Binary file
data/lib/1.9/free.so ADDED
Binary file
data/lib/free.rb ADDED
@@ -0,0 +1,33 @@
1
+ # free.rb
2
+ # (C) John Mair (banisterfiend); MIT license
3
+
4
+ direc = File.dirname(__FILE__)
5
+
6
+ require "#{direc}/free/version"
7
+
8
+ # @author John Mair (banisterfiend)
9
+ module Free
10
+
11
+ # Force garbage collection on an object and free its internal structures.
12
+ # @return nil
13
+ # @example
14
+ # h = "hello"
15
+ # h.free
16
+ def free() end
17
+ end
18
+
19
+ begin
20
+ if RUBY_VERSION =~ /1.9/
21
+ require "#{direc}/1.9/free"
22
+ else
23
+ require "#{direc}/1.8/free"
24
+ end
25
+ rescue LoadError => e
26
+ require "rbconfig"
27
+ dlext = Config::CONFIG['DLEXT']
28
+ require "#{direc}/free.#{dlext}"
29
+ end
30
+
31
+ class Object
32
+ include Free
33
+ end
@@ -0,0 +1,3 @@
1
+ module Free
2
+ VERSION = "0.1.0"
3
+ end
data/test/test.rb ADDED
@@ -0,0 +1,35 @@
1
+ direc = File.dirname(__FILE__)
2
+
3
+ require 'rubygems'
4
+ require "#{direc}/../lib/free"
5
+ require 'bacon'
6
+
7
+ puts "Testing free version #{Free::VERSION}..."
8
+ puts "Ruby version: #{RUBY_VERSION}"
9
+
10
+ describe Free do
11
+
12
+ ["hello", Object.new, Class.new, /hello/, [], {}, 10.5].each do |v|
13
+ it "should free a #{v.class}" do
14
+ v
15
+ # make sure test doesn't pass as a result of normal garbage
16
+ # collection, so keep a reference to v
17
+ c = v
18
+
19
+ # grab the object id since referring to object directly (through
20
+ # c) will likely result in segfault, which can't be rescued.
21
+ id = v.object_id
22
+
23
+ ObjectSpace._id2ref(id).should == v
24
+
25
+ # free it
26
+ v.free
27
+
28
+ # Two things may happen if it is properly freed:
29
+ # 1. The _id2ref resolves to another object (the free slot is
30
+ # replace by a new object)
31
+ # 2. Calling _id2ref raises an exception, typically a RangeError
32
+ (ObjectSpace._id2ref(id) != v || lambda { ObjectSpace._id2ref(id) } rescue true).should == true
33
+ end
34
+ end
35
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: free
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: i386-mingw32
11
+ authors:
12
+ - John Mair (banisterfiend)
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-01-02 00:00:00 +13:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Force immediate garbage collection of an object.
22
+ email: jrmair@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - ext/free/extconf.rb
31
+ - ext/free/compat.h
32
+ - ext/free/free.h
33
+ - ext/free/free.c
34
+ - lib/free/version.rb
35
+ - lib/free.rb
36
+ - test/test.rb
37
+ - HISTORY
38
+ - README.md
39
+ - Rakefile
40
+ - lib/1.8/free.so
41
+ - lib/1.9/free.so
42
+ has_rdoc: yard
43
+ homepage: http://banisterfiend.wordpress.com
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options: []
48
+
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ requirements: []
68
+
69
+ rubyforge_project:
70
+ rubygems_version: 1.3.7
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Force immediate garbage collection of an object.
74
+ test_files: []
75
+