Skip to content
This repository was archived by the owner on Mar 15, 2022. It is now read-only.

Commit 3766879

Browse files
committed
Merge pull request #15 from ruby-concurrency/initial-updates
Initial updates
2 parents e1462f4 + f22e34a commit 3766879

19 files changed

+158
-93
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@ tmp
33
rdoc
44
*.rbc
55
coverage
6-
.ruby-version
6+
.ruby-version
7+
.ruby-gemset
8+
Gemfile.lock

.travis.yml

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
1+
language: ruby
2+
13
rvm:
2-
- 1.8.7
3-
- 1.9.2
4-
- rbx
5-
- jruby
4+
- 2.2.0
5+
- 2.1.5
6+
- 2.1.4
7+
- 2.0.0
8+
- 1.9.3
9+
- ruby-head
10+
- jruby-1.7.18
11+
- jruby-head
12+
- rbx-2
13+
14+
jdk:
15+
- oraclejdk8
16+
17+
sudo: false
18+
19+
branches:
20+
only:
21+
- master
22+
23+
matrix:
24+
allow_failures:
25+
- rvm: ruby-head
26+
- rvm: jruby-head
27+
- rvm: 1.9.3

Gemfile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
source 'https://rubygems.org'
2+
3+
gemspec
4+
5+
group :development do
6+
gem 'rake', '~> 10.3.2'
7+
end
8+
9+
group :testing do
10+
gem 'test-unit', '~> 3.0.9'
11+
#gem 'rspec', '~> 3.0.0'
12+
#gem 'simplecov', '~> 0.8.2', :require => false
13+
gem 'coveralls', '~> 0.7.3', :require => false
14+
end
15+
16+
group :documentation do
17+
gem 'yard', '~> 0.8.7.4', :require => false
18+
gem 'inch', '~> 0.4.6', :platforms => :mri, :require => false
19+
gem 'redcarpet', '~> 3.1.2', platforms: :mri # understands github markdown
20+
end

README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Ref
2+
3+
[![Gem Version](https://badge.fury.io/rb/ref.svg)](http://badge.fury.io/rb/ref) [![Build Status](https://travis-ci.org/ruby-concurrency/ref.svg?branch=master)](https://travis-ci.org/ruby-concurrency/ref) [![Coverage Status](https://img.shields.io/coveralls/ruby-concurrency/ref/master.svg)](https://coveralls.io/r/ruby-concurrency/ref) [![Code Climate](https://codeclimate.com/github/ruby-concurrency/ref.svg)](https://codeclimate.com/github/ruby-concurrency/ref) [![Dependency Status](https://gemnasium.com/ruby-concurrency/ref.svg)](https://gemnasium.com/ruby-concurrency/ref) [![License](https://img.shields.io/badge/license-MIT-green.svg)](http://opensource.org/licenses/MIT) [![Gitter chat](http://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/ruby-concurrency/concurrent-ruby)
4+
5+
This library provides object references for Ruby as well as some common utilities for working with references. Object references are used to point to other objects and come in three distinct flavors that interact differently with the garbage collector.
6+
7+
* `Ref::StrongReference` - This is a plain old pointer to another object.
8+
* `Ref::WeakReference` - This is a pointer to another object, but it is not seen by the garbage collector and the memory used by the object can be reclaimed at any time.
9+
* `Ref::SoftReference` - This is similar to a weak reference, but the garbage collector is not as eager to reclaim the referenced object.
10+
11+
All of these classes extend from a common `Ref::Reference` class and have a common interface.
12+
13+
Weak and soft references are useful when you have instantiated objects that you may want to use again but can recreate if necessary. Since the garbage collector determines when to reclaim the memory used by the objects, you don't need to worry about bloating the Ruby heap.
14+
15+
## Example Usage
16+
17+
```ruby
18+
ref = Ref::WeakReference.new("hello")
19+
ref.object # should be "hello"
20+
ObjectSpace.garbage_collect
21+
ref.object # should be nil (assuming the garbage collector reclaimed the reference)
22+
```
23+
24+
## Goodies
25+
26+
This library also includes tools for some common uses of weak and soft references.
27+
28+
* `Ref::WeakKeyMap` - A map of keys to values where the keys are weak references
29+
* `Ref::WeakValueMap` - A map of keys to values where the values are weak references
30+
* `Ref::SoftKeyMap` - A map of keys to values where the keys are soft references
31+
* `Ref::SoftValueMap` - A map of keys to values where the values are soft references
32+
* `Ref::ReferenceQueue` - A thread safe implementation of a queue that will add references to itself as their objects are garbage collected.
33+
34+
## Problems with WeakRef
35+
36+
Ruby does come with the `WeakRef` class in the standard library. However, there are [issues with this class](https://bugs.ruby-lang.org/issues/4168) across several different Ruby runtimes. This gem provides a common interface to weak references that works across MRI, Ruby Enterprise Edition, YARV, Jruby, Rubinius, and IronRuby.
37+
38+
1. MRI and REE 1.8 - `WeakRef` extends from Delegator which is a very heavy weight class under Ruby 1.8. Creating a `WeakRef` object will allocate thousands of other objects and use up hundreds of kilobytes of memory. This makes `WeakRef` all but unusable even if you only need several hundred of them.
39+
2. YARV 1.9 - `WeakRef` is unsafe to use because the garbage collector can run in a different system thread than a thread allocating memory. This exposes a bug where a `WeakRef` may end up pointing to a completely different object than it originally referenced.
40+
3. Jruby and IronRuby - Jruby and IronRuby using the Ruby 1.8 libraries suffers from the same performance issue with the Delegator class. Furthermore, these VM's don't implement the method used to load an object from the heap using an object id and so cannot use a pure Ruby method to implement weak references.
41+
4. Rubinius - Rubinius implements `WeakRef` with a lighter weight version of delegation and works very well.
42+
5. MRI Ruby 2.0 has a good implementation of `WeakRef`.
43+
44+
## BasicObject
45+
46+
Note that weak references will not work with MRI 1.9 or earlier. References will be created, but the objects will never be stored so the reference object will always treat the object as if it is always garbage collected. BasicObject does not implement the necessary methods to maintain the reference.

README.rdoc

Lines changed: 0 additions & 40 deletions
This file was deleted.

VERSION

Lines changed: 0 additions & 1 deletion
This file was deleted.

lib/ref.rb

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
module Ref
2-
require File.join(File.dirname(__FILE__), "ref", "abstract_reference_value_map.rb")
3-
require File.join(File.dirname(__FILE__), "ref", "abstract_reference_key_map.rb")
4-
require File.join(File.dirname(__FILE__), "ref", "reference.rb")
5-
require File.join(File.dirname(__FILE__), "ref", "reference_queue.rb")
6-
require File.join(File.dirname(__FILE__), "ref", "safe_monitor.rb")
2+
require 'ref/abstract_reference_value_map'
3+
require 'ref/abstract_reference_key_map'
4+
require 'ref/reference'
5+
require 'ref/reference_queue'
6+
require 'ref/safe_monitor'
77

88
# Set the best implementation for weak references based on the runtime.
99
if defined?(RUBY_PLATFORM) && RUBY_PLATFORM == 'java'
@@ -15,31 +15,28 @@ module Ref
1515
$LOAD_PATH.shift if $LOAD_PATH.first == File.dirname(__FILE__)
1616
end
1717
else
18-
require File.join(File.dirname(__FILE__), "ref", "soft_reference.rb")
18+
require 'ref/soft_reference'
1919
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ironruby'
2020
# IronRuby has it's own implementation of weak references.
21-
require File.join(File.dirname(__FILE__), "ref", "weak_reference", "iron_ruby.rb")
21+
require 'ref/weak_reference/iron_ruby'
2222
elsif defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
2323
# If using Rubinius set the implementation to use WeakRef since it is very efficient and using finalizers is not.
24-
require File.join(File.dirname(__FILE__), "ref", "weak_reference", "weak_ref.rb")
24+
require 'ref/weak_reference/weak_ref'
2525
elsif defined?(::ObjectSpace::WeakMap)
2626
# Ruby 2.0 has a working implementation of weakref.rb backed by the new ObjectSpace::WeakMap
27-
require File.join(File.dirname(__FILE__), "ref", "weak_reference", "weak_ref.rb")
27+
require 'ref/weak_reference/weak_ref'
2828
elsif defined?(::ObjectSpace._id2ref)
2929
# If ObjectSpace can lookup objects from their object_id, then use the pure ruby implementation.
30-
require File.join(File.dirname(__FILE__), "ref", "weak_reference", "pure_ruby.rb")
30+
require 'ref/weak_reference/pure_ruby'
3131
else
3232
# Otherwise, wrap the standard library WeakRef class
33-
require File.join(File.dirname(__FILE__), "ref", "weak_reference", "weak_ref.rb")
33+
require 'ref/weak_reference/weak_ref'
3434
end
3535
end
36-
37-
require File.join(File.dirname(__FILE__), "ref", "soft_key_map.rb")
38-
require File.join(File.dirname(__FILE__), "ref", "soft_value_map.rb")
39-
require File.join(File.dirname(__FILE__), "ref", "strong_reference.rb")
40-
require File.join(File.dirname(__FILE__), "ref", "weak_key_map.rb")
41-
require File.join(File.dirname(__FILE__), "ref", "weak_value_map.rb")
42-
43-
# Used for testing
44-
autoload :Mock, File.join(File.dirname(__FILE__), "ref", "mock.rb")
36+
37+
require 'ref/soft_key_map'
38+
require 'ref/soft_value_map'
39+
require 'ref/strong_reference'
40+
require 'ref/weak_key_map'
41+
require 'ref/weak_value_map'
4542
end

lib/ref/version.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module Ref
2+
VERSION = '1.0.5'
3+
end

ref.gemspec

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
1+
$:.push File.join(File.dirname(__FILE__), 'lib')
2+
3+
require 'ref/version'
4+
15
Gem::Specification.new do |s|
2-
s.name = 'ref'
3-
s.version = File.read(File.expand_path("../VERSION", __FILE__)).strip
4-
s.summary = "Library that implements weak, soft, and strong references in Ruby."
6+
s.name = 'ref'
7+
s.version = Ref::VERSION
8+
s.authors = ['Brian Durand']
9+
s.email = ['[email protected]']
10+
s.homepage = "http://github.com/ruby-concurrency/ref"
11+
s.summary = "Library that implements weak, soft, and strong references in Ruby."
512
s.description = "Library that implements weak, soft, and strong references in Ruby that work across multiple runtimes (MRI, REE, YARV, Jruby, Rubinius, and IronRuby). Also includes implementation of maps/hashes that use references and a reference queue."
13+
s.license = "MIT"
14+
s.date = Time.now.strftime('%Y-%m-%d')
615

7-
s.authors = ['Brian Durand']
8-
s.email = ['[email protected]']
9-
s.homepage = "http://github.com/bdurand/ref"
16+
s.files = ['README.md', 'MIT_LICENSE']
17+
s.files += Dir['lib/**/*.*']
18+
s.files += Dir['ext/**/*.*']
19+
s.files += Dir['test/**/*.*']
1020

11-
s.files = ['README.rdoc', 'VERSION', 'MIT_LICENSE'] + Dir.glob('lib/**/*'), Dir.glob('test/**/*'), Dir.glob('ext/**/*')
12-
s.require_path = 'lib'
21+
s.require_paths = ['lib']
1322

14-
s.has_rdoc = true
15-
s.rdoc_options = ["--charset=UTF-8", "--main", "README.rdoc"]
16-
s.extra_rdoc_files = ["README.rdoc"]
17-
18-
s.license = "MIT"
23+
s.has_rdoc = true
24+
s.rdoc_options = ["--charset=UTF-8", "--main", "README.md"]
25+
s.extra_rdoc_files = ["README.md"]
26+
27+
s.required_ruby_version = '>= 1.9.3'
1928
end

test/mock_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
require File.expand_path("../test_helper", __FILE__)
1+
require_relative 'test_helper'
22

33
class TestMock < Test::Unit::TestCase
44
def test_gc_with_argument

0 commit comments

Comments
 (0)