-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Weak references are implemented by boehm's register_disappearing_link
- v0.24.1
- 1.15.1
- 1.15.0
- 1.14.1
- 1.14.0
- 1.13.3
- 1.13.2
- 1.13.1
- 1.13.0
- 1.12.2
- 1.12.1
- 1.12.0
- 1.11.2
- 1.11.1
- 1.11.0
- 1.10.1
- 1.10.0
- 1.9.2
- 1.9.1
- 1.9.0
- 1.8.2
- 1.8.1
- 1.8.0
- 1.7.3
- 1.7.2
- 1.7.1
- 1.7.0
- 1.6.2
- 1.6.1
- 1.6.0
- 1.5.1
- 1.5.0
- 1.4.1
- 1.4.0
- 1.3.2
- 1.3.1
- 1.3.0
- 1.2.2
- 1.2.1
- 1.2.0
- 1.1.1
- 1.1.0
- 1.0.0
- 0.36.1
- 0.36.0
- 0.35.1
- 0.35.0
- 0.34.0
- 0.33.0
- 0.32.1
- 0.32.0
- 0.31.1
- 0.31.0
- 0.30.1
- 0.30.0
- 0.29.0
- 0.28.0
- 0.27.2
- 0.27.1
- 0.27.0
- 0.26.1
- 0.26.0
- 0.25.1
- 0.25.0
- 0.24.2
- 0.24.1
- 0.24.0
- 0.23.1
- 0.23.0
- 0.22.0
- 0.21.1
- 0.21.0
- 0.20.5
- 0.20.4
- 0.20.3
- 0.20.2
- 0.20.1
- 0.20.0
- 0.19.4
- 0.19.3
- 0.19.2
- 0.19.1
Showing
3 changed files
with
100 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
require "spec" | ||
require "weak_ref" | ||
|
||
module WeakRefSpec | ||
class State | ||
@@count = {} of Symbol => Int64 | ||
|
||
def self.inc(key) | ||
@@count[key] = @@count.fetch(key, 0i64) + 1 | ||
end | ||
|
||
def self.count(key) | ||
@@count.fetch(key, 0i64) | ||
end | ||
|
||
def self.reset | ||
@@count.clear | ||
end | ||
end | ||
|
||
class Foo | ||
def initialize(@key : Symbol) | ||
end | ||
|
||
def finalize | ||
State.inc @key | ||
end | ||
end | ||
end | ||
|
||
describe WeakRef do | ||
it "should get dereference object" do | ||
foo = WeakRefSpec::Foo.new :foo | ||
ref = WeakRef.new(foo) | ||
ref.should_not be_nil | ||
ref.target.should be(foo) | ||
end | ||
|
||
it "WeakRefSpec::State counts released objects" do | ||
WeakRefSpec::State.reset | ||
WeakRefSpec::State.count(:foo).should eq 0 | ||
10.times do | ||
WeakRefSpec::Foo.new(:foo) | ||
end | ||
GC.collect | ||
WeakRefSpec::State.count(:foo).should be > 0 | ||
end | ||
|
||
it "Referenced object should not be released" do | ||
WeakRefSpec::State.reset | ||
instances = [] of WeakRefSpec::Foo | ||
WeakRefSpec::State.count(:strong_foo_ref).should eq 0 | ||
10.times do | ||
instances << WeakRefSpec::Foo.new(:strong_foo_ref) | ||
end | ||
GC.collect | ||
WeakRefSpec::State.count(:strong_foo_ref).should eq 0 | ||
end | ||
|
||
it "Weak referenced object should be released if no other reference" do | ||
WeakRefSpec::State.reset | ||
instances = [] of WeakRef(WeakRefSpec::Foo) | ||
last = nil | ||
10.times do | ||
last = WeakRefSpec::Foo.new(:weak_foo_ref) | ||
instances << WeakRef.new(last) | ||
end | ||
GC.collect | ||
WeakRefSpec::State.count(:weak_foo_ref).should be > 0 | ||
instances.select { |wr| wr.target.nil? }.size.should be > 0 | ||
instances[-1].target.should_not be_nil | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Weak Reference class that allows a referenced object to be garbage-collected. | ||
# | ||
class WeakRef(T) | ||
@target : Void* | ||
|
||
def initialize(target : T) | ||
@target = target.as(Void*) | ||
GC.register_disappearing_link(pointerof(@target)) | ||
end | ||
|
||
def self.allocate | ||
GC.malloc_atomic(sizeof(self)).as(self) | ||
end | ||
|
||
# Returns the referenced object or `Nil` if it has been garbage-collected. | ||
def target | ||
@target.as(T?) | ||
end | ||
end |