Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: c49cf6146126
Choose a base ref
...
head repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: f40bcb3f6ba7
Choose a head ref
  • 2 commits
  • 3 files changed
  • 1 contributor

Commits on Apr 19, 2017

  1. WeakRef: Do not register non heap pointers as diasappearing links

    This should allow at least pointers to the data section
    to work seamlessly with WeakRef and in some cases even
    allow stack pointers to be passed, for the crazy
    jhass authored and bcardiff committed Apr 19, 2017
    Copy the full SHA
    8b0fd63 View commit details
  2. Rename WeakRef#target to WeakRef#value

    value is consistent with pointer
    
    Additionally target feels like it's leaking implementation details as
    that's the name of the internal instance variable too
    jhass authored and bcardiff committed Apr 19, 2017
    Copy the full SHA
    f40bcb3 View commit details
Showing with 25 additions and 6 deletions.
  1. +16 −4 spec/std/weak_ref_spec.cr
  2. +5 −0 src/gc/boehm.cr
  3. +4 −2 src/weak_ref.cr
20 changes: 16 additions & 4 deletions spec/std/weak_ref_spec.cr
Original file line number Diff line number Diff line change
@@ -27,11 +27,23 @@ private class Foo
end

describe WeakRef do
it "should get dereference object" do
it "should get dereferenced object" do
foo = Foo.new :foo
ref = WeakRef.new(foo)
ref.should_not be_nil
ref.target.should be(foo)
ref.value.should be(foo)
end

it "should get dereferenced object in data section" do
foo = "foo"
ref = WeakRef.new(foo)
ref.value.should be(foo)
end

it "should not crash with object in data section during GC" do
foo = "foo"
ref = WeakRef.new(foo)
GC.collect
end

it "State counts released objects" do
@@ -65,7 +77,7 @@ describe WeakRef do
end
GC.collect
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
instances.select { |wr| wr.value.nil? }.size.should be > 0
instances[-1].value.should_not be_nil
end
end
5 changes: 5 additions & 0 deletions src/gc/boehm.cr
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@ lib LibGC
fun set_handle_fork = GC_set_handle_fork(value : Int)

fun base = GC_base(displaced_pointer : Void*) : Void*
fun is_heap_ptr = GC_is_heap_ptr(pointer : Void*) : Int
fun general_register_disappearing_link = GC_general_register_disappearing_link(link : Void**, obj : Void*) : Int

type Finalizer = Void*, Void* ->
@@ -120,6 +121,10 @@ module GC
LibGC.general_register_disappearing_link(pointer, base)
end

def self.is_heap_ptr(pointer : Void*)
LibGC.is_heap_ptr(pointer) != 0
end

record Stats,
# collections : LibC::ULong,
# bytes_found : LibC::Long,
6 changes: 4 additions & 2 deletions src/weak_ref.cr
Original file line number Diff line number Diff line change
@@ -5,7 +5,9 @@ class WeakRef(T)

def initialize(target : T)
@target = target.as(Void*)
GC.register_disappearing_link(pointerof(@target))
if GC.is_heap_ptr(@target)
GC.register_disappearing_link(pointerof(@target))
end
end

def self.allocate
@@ -15,7 +17,7 @@ class WeakRef(T)
end

# Returns the referenced object or `Nil` if it has been garbage-collected.
def target
def value
@target.as(T?)
end
end