weakling 0.0.4-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,16 @@
1
+ == 0.0.3 ==
2
+
3
+ * Moved all classes under Weakling module
4
+ * WeakRef no longer extends Delegate
5
+ * WeakRef#__getobj__ is now just #get
6
+ * IdHash now includes Enumerable
7
+ * Added specs for most behavior
8
+
9
+ == 0.0.2 ==
10
+
11
+ * Minor compatibility tweak for the WeakRef replacement impl, to match JRuby
12
+
13
+ == 0.0.1 ==
14
+
15
+ * Initial release
16
+ * RefQueue and IdHash support
@@ -0,0 +1,60 @@
1
+ weakling: a collection of weakref utilities for Ruby
2
+
3
+ == Summary ==
4
+
5
+ This library provides:
6
+
7
+ * a modified WeakRef implementation for JRuby that supports a reference queue
8
+ * a WeakRef::RefQueue class
9
+ * a weak-valued ID map to replace typical uses of _id2ref
10
+
11
+ In the future it may provide additional features like a generic WeakHash or other
12
+ reference types like soft and phantom references.
13
+
14
+ The weakling repository is at http://github.com/headius/weakling.
15
+
16
+ == Usage ==
17
+
18
+ Just require 'weakling'. It will require 'weakref' along with the refqueue JRuby
19
+ extension and the weakling/collections library containing the weak id hash.
20
+
21
+ == RefQueue Example ==
22
+
23
+ require 'weakling'
24
+ require 'java'
25
+
26
+ q = WeakRef::RefQueue.new
27
+ wr = WeakRef.new(Object.new, q)
28
+ puts "weakref object: #{wr.__id__}"
29
+
30
+ puts "running GC"
31
+ java.lang.System.gc
32
+
33
+ puts "weakref alive?: #{wr.weakref_alive?}"
34
+ puts "weakref object from queue: #{q.poll.__id__}"
35
+
36
+ == WeakRef::IdHash Example ==
37
+
38
+ require 'weakling'
39
+
40
+ wh = WeakRef::IdHash.new
41
+
42
+ ary = (1..10).to_a.map {Object.new}
43
+ ids = ary.map {|o| wh.add(o)}
44
+
45
+ puts "all items in weak_id_hash:"
46
+ ids.each {|i| puts "#{i} = #{wh[i]}"}
47
+
48
+ puts "dereferencing objects"
49
+ ary = nil
50
+
51
+ puts "forcing GC"
52
+ begin
53
+ require 'java'
54
+ java.lang.System.gc
55
+ rescue
56
+ GC.start
57
+ end
58
+
59
+ puts "all items in weak id hash:"
60
+ ids.each {|i| puts "#{i} = #{wh[i]}"}
@@ -0,0 +1,28 @@
1
+ require 'ant'
2
+
3
+ directory "pkg/classes"
4
+
5
+ desc "Clean up build artifacts"
6
+ task :clean do
7
+ rm_rf "pkg/classes"
8
+ rm_rf "lib/refqueue.jar"
9
+ end
10
+
11
+ desc "Compile the extension"
12
+ task :compile => "pkg/classes" do |t|
13
+ ant.javac :srcdir => "ext", :destdir => t.prerequisites.first,
14
+ :source => "1.5", :target => "1.5", :debug => true,
15
+ :classpath => "${java.class.path}:${sun.boot.class.path}"
16
+ end
17
+
18
+ desc "Build the jar"
19
+ task :jar => :compile do
20
+ ant.jar :basedir => "pkg/classes", :destfile => "lib/refqueue.jar", :includes => "**/*.class"
21
+ end
22
+
23
+ task :package => :jar
24
+
25
+ desc "Run the specs"
26
+ task :spec => :jar do
27
+ ruby "-S", "spec", "spec"
28
+ end
@@ -0,0 +1,24 @@
1
+ require 'weakling'
2
+
3
+ wh = WeakRef::IdHash.new
4
+
5
+ ary = (1..10).to_a.map {Object.new}
6
+ ids = ary.map {|o| wh.add(o)}
7
+
8
+ puts "all items in weak_id_hash:"
9
+ ids.each {|i| puts "#{i} = #{wh[i]}"}
10
+
11
+ puts "dereferencing objects"
12
+ ary = nil
13
+
14
+ puts "forcing GC"
15
+ begin
16
+ require 'java'
17
+ java.lang.System.gc
18
+ rescue LoadError
19
+ # not on JRuby, use GC.start
20
+ GC.start
21
+ end
22
+
23
+ puts "all items in weak id hash:"
24
+ ids.each {|i| puts "#{i} = #{wh[i]}"}
@@ -0,0 +1,13 @@
1
+ require 'weakling'
2
+ require 'java'
3
+
4
+ q = WeakRef::RefQueue.new
5
+ wr = WeakRef.new(Object.new, q)
6
+ puts "weakref object: #{wr.__id__}"
7
+
8
+ puts "running GC"
9
+ java.lang.System.gc
10
+
11
+ puts "weakref alive?: #{wr.weakref_alive?}"
12
+ puts "weakref object from queue: #{q.poll.__id__}"
13
+
@@ -0,0 +1,12 @@
1
+ import java.io.IOException;
2
+
3
+ import org.jruby.Ruby;
4
+ import org.jruby.runtime.load.BasicLibraryService;
5
+
6
+ public class RefqueueService implements BasicLibraryService {
7
+ public boolean basicLoad(final Ruby runtime) throws IOException {
8
+ new org.jruby.ext.RefQueueLibrary().load(runtime, false);
9
+ return true;
10
+ }
11
+ }
12
+
@@ -0,0 +1,164 @@
1
+ package org.jruby.ext;
2
+
3
+ import java.io.IOException;
4
+ import java.lang.ref.ReferenceQueue;
5
+ import java.lang.ref.WeakReference;
6
+ import org.jruby.Ruby;
7
+ import org.jruby.RubyClass;
8
+ import org.jruby.RubyException;
9
+ import org.jruby.RubyKernel;
10
+ import org.jruby.RubyModule;
11
+ import org.jruby.RubyObject;
12
+ import org.jruby.anno.JRubyMethod;
13
+ import org.jruby.anno.JRubyClass;
14
+ import org.jruby.exceptions.RaiseException;
15
+ import org.jruby.runtime.Block;
16
+ import org.jruby.runtime.ObjectAllocator;
17
+ import org.jruby.runtime.ThreadContext;
18
+ import org.jruby.runtime.Visibility;
19
+ import org.jruby.runtime.builtin.IRubyObject;
20
+ import org.jruby.runtime.load.Library;
21
+
22
+ /**
23
+ * This library adds reference queue support to JRuby's weakrefs by adding a
24
+ * RefQueue class that wraps a Java ReferenceQueue and replacing the built-in
25
+ * WeakRef impl with a new one that's aware of RefQueue.
26
+ *
27
+ * @author headius
28
+ */
29
+ public class RefQueueLibrary implements Library {
30
+ public void load(Ruby runtime, boolean wrap) throws IOException {
31
+ // only used for RefError
32
+ RubyKernel.require(runtime.getKernel(), runtime.newString("weakref"), Block.NULL_BLOCK);
33
+
34
+ RubyModule weaklingModule = runtime.getOrCreateModule("Weakling");
35
+ RubyClass weakrefClass = runtime.defineClassUnder("WeakRef", runtime.getObject(), WEAKREF_ALLOCATOR, weaklingModule);
36
+ weakrefClass.setAllocator(WEAKREF_ALLOCATOR);
37
+ weakrefClass.defineAnnotatedMethods(WeakRef.class);
38
+
39
+ RubyClass refQueueClass = runtime.defineClassUnder("RefQueue", runtime.getObject(), REFQUEUE_ALLOCATOR, weaklingModule);
40
+ refQueueClass.defineAnnotatedMethods(RefQueue.class);
41
+ }
42
+
43
+ private static final ObjectAllocator WEAKREF_ALLOCATOR = new ObjectAllocator() {
44
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
45
+ return new WeakRef(runtime, klazz);
46
+ }
47
+ };
48
+
49
+ private static final ObjectAllocator REFQUEUE_ALLOCATOR = new ObjectAllocator() {
50
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
51
+ return new RefQueue(runtime, klazz);
52
+ }
53
+ };
54
+
55
+ @JRubyClass(name="RefQueue", parent="Object")
56
+ public static class RefQueue extends RubyObject {
57
+ private final ReferenceQueue queue;
58
+
59
+ public RefQueue(Ruby runtime, RubyClass klass) {
60
+ super(runtime, klass);
61
+ queue = new ReferenceQueue();
62
+ }
63
+
64
+ public ReferenceQueue getQueue() {
65
+ return queue;
66
+ }
67
+
68
+ @JRubyMethod
69
+ public IRubyObject poll() {
70
+ return returnable(queue.poll());
71
+ }
72
+
73
+ @JRubyMethod
74
+ public IRubyObject remove() {
75
+ try {
76
+ return returnable(queue.remove());
77
+ } catch (InterruptedException ie) {
78
+ // ignore
79
+ return getRuntime().getNil();
80
+ }
81
+ }
82
+
83
+ @JRubyMethod
84
+ public IRubyObject remove(IRubyObject timeout) {
85
+ try {
86
+ return returnable(queue.remove(timeout.convertToInteger().getLongValue()));
87
+ } catch (InterruptedException ie) {
88
+ // ignore
89
+ return getRuntime().getNil();
90
+ }
91
+ }
92
+
93
+ private IRubyObject returnable(Object result) {
94
+ RubyWeakReference ref = (RubyWeakReference)result;
95
+ if (ref == null) return getRuntime().getNil();
96
+ return ref.getWeakRef();
97
+ }
98
+ }
99
+
100
+ public static class RubyWeakReference extends WeakReference<IRubyObject> {
101
+ private final WeakRef ref;
102
+ public RubyWeakReference(IRubyObject obj, WeakRef ref) {
103
+ super(obj);
104
+ this.ref = ref;
105
+ }
106
+ public RubyWeakReference(IRubyObject obj, WeakRef ref, ReferenceQueue queue) {
107
+ super(obj, queue);
108
+ this.ref = ref;
109
+ }
110
+ public WeakRef getWeakRef() {
111
+ return ref;
112
+ }
113
+ }
114
+
115
+ public static class WeakRef extends RubyObject {
116
+ private RubyWeakReference ref;
117
+
118
+ public WeakRef(Ruby runtime, RubyClass klazz) {
119
+ super(runtime, klazz);
120
+ }
121
+
122
+ @JRubyMethod(name = "get")
123
+ public IRubyObject get() {
124
+ IRubyObject obj = ref.get();
125
+
126
+ if (obj == null) {
127
+ // FIXME weakref.rb also does caller(2) here for the backtrace
128
+ throw newRefError("Illegal Reference - probably recycled");
129
+ }
130
+
131
+ return obj;
132
+ }
133
+
134
+ @JRubyMethod(name = "initialize", frame = true, visibility = Visibility.PRIVATE)
135
+ public IRubyObject initialize(ThreadContext context, IRubyObject obj) {
136
+ ref = new RubyWeakReference(obj, this);
137
+
138
+ return context.getRuntime().getNil();
139
+ }
140
+
141
+ @JRubyMethod(name = "initialize", frame = true, visibility = Visibility.PRIVATE)
142
+ public IRubyObject initialize(ThreadContext context, IRubyObject obj, IRubyObject queue) {
143
+ if (!(queue instanceof RefQueue)) {
144
+ throw getRuntime().newTypeError("WeakRef can only queue into a RefQueue");
145
+ }
146
+ ref = new RubyWeakReference(obj, this, ((RefQueue)queue).getQueue());
147
+
148
+ return context.getRuntime().getNil();
149
+ }
150
+
151
+ @JRubyMethod(name = "weakref_alive?")
152
+ public IRubyObject weakref_alive_p() {
153
+ return ref.get() != null ? getRuntime().getTrue() : getRuntime().getFalse();
154
+ }
155
+
156
+ private RaiseException newRefError(String message) {
157
+ RubyException exception =
158
+ (RubyException)getRuntime().getClass("RefError").newInstance(getRuntime().getCurrentContext(),
159
+ new IRubyObject[] {getRuntime().newString(message)}, Block.NULL_BLOCK);
160
+
161
+ return new RaiseException(exception);
162
+ }
163
+ }
164
+ }
Binary file
@@ -0,0 +1,2 @@
1
+ require 'refqueue'
2
+ require 'weakling/collections.rb'
@@ -0,0 +1,48 @@
1
+ require 'refqueue'
2
+
3
+ module Weakling
4
+ class IdHash
5
+ include Enumerable
6
+
7
+ def initialize
8
+ @hash = Hash.new
9
+ @queue = Weakling::RefQueue.new
10
+ end
11
+
12
+ class IdWeakRef < Weakling::WeakRef
13
+ attr_accessor :id
14
+ def initialize(obj, queue)
15
+ super(obj, queue)
16
+ @id = obj.__id__
17
+ end
18
+ end
19
+
20
+ def [](id)
21
+ _cleanup
22
+ if wr = @hash[id]
23
+ return wr.get rescue nil
24
+ end
25
+
26
+ return nil
27
+ end
28
+
29
+ def add(object)
30
+ _cleanup
31
+ wr = IdWeakRef.new(object, @queue)
32
+
33
+ @hash[wr.id] = wr
34
+
35
+ return wr.id
36
+ end
37
+
38
+ def _cleanup
39
+ while ref = @queue.poll
40
+ @hash.delete(ref.id)
41
+ end
42
+ end
43
+
44
+ def each
45
+ @hash.each {|id, wr| obj = wr.get rescue nil; yield [id,obj] if obj}
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,16 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{weakling}
5
+ s.version = "0.0.4"
6
+ s.authors = ["Charles Oliver Nutter"]
7
+ s.date = Time.now.strftime('YYYY-MM-DD')
8
+ s.description = "A modified WeakRef impl for JRuby plus some weakref-related tools"
9
+ s.email = ["headius@headius.com"]
10
+ s.files = Dir['{lib,ext,examples,test}/**/*'] + Dir['{*.txt,*.gemspec,Rakefile}']
11
+ s.homepage = "http://github.com/headius/weakling"
12
+ s.require_paths = ["lib"]
13
+ s.summary = "A modified WeakRef impl for JRuby plus some weakref-related tools"
14
+ s.test_files = Dir["test/test*.rb"]
15
+ s.platform = "java"
16
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: weakling
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 4
9
+ version: 0.0.4
10
+ platform: java
11
+ authors:
12
+ - Charles Oliver Nutter
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-06-03 18:51:00.994000 -05:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: A modified WeakRef impl for JRuby plus some weakref-related tools
22
+ email:
23
+ - headius@headius.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - lib/refqueue.jar
32
+ - lib/weakling.rb
33
+ - lib/weakling/collections.rb
34
+ - ext/RefqueueService.java
35
+ - ext/org/jruby/ext/RefQueueLibrary.java
36
+ - examples/id_hash.rb
37
+ - examples/refqueue_use.rb
38
+ - HISTORY.txt
39
+ - README.txt
40
+ - weakling.gemspec
41
+ - Rakefile
42
+ has_rdoc: true
43
+ homepage: http://github.com/headius/weakling
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: A modified WeakRef impl for JRuby plus some weakref-related tools
74
+ test_files: []
75
+