weakling 0.0.4-java

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.
@@ -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
+