Skip to content

Commit

Permalink
add finalize function to force finalization
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Dec 5, 2014
1 parent 200b030 commit 2df759a
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 18 deletions.
2 changes: 2 additions & 0 deletions base/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ function finalizer(o::ANY, f::Union(Function,Ptr))
ccall(:jl_gc_add_finalizer, Void, (Any,Any), o, f)
end

finalize(o::ANY) = ccall(:jl_finalize, Void, (Any,), o)

gc() = ccall(:jl_gc_collect, Void, ())
gc_enable() = ccall(:jl_gc_enable, Void, ())
gc_disable() = ccall(:jl_gc_disable, Void, ())
Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,7 @@ export

# RTS internals
finalizer,
finalize,
gc,
gc_disable,
gc_enable,
Expand Down
4 changes: 4 additions & 0 deletions doc/stdlib/base.rst
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ All Objects

Register a function ``f(x)`` to be called when there are no program-accessible references to ``x``. The behavior of this function is unpredictable if ``x`` is of a bits type.

.. function:: finalize(x)

Immediately run finalizers registered for object ``x``.

.. function:: copy(x)

Create a shallow copy of ``x``: the outer structure is copied, but not all internal values. For example, copying an array produces a new array with identically-same elements as the original.
Expand Down
49 changes: 31 additions & 18 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,11 @@ static void schedule_finalization(void *o)
static void run_finalizer(jl_value_t *o, jl_value_t *ff)
{
jl_function_t *f;
while (jl_is_tuple(ff)) {
f = (jl_function_t*)jl_t0(ff);
while (1) {
if (jl_is_tuple(ff))
f = (jl_function_t*)jl_t0(ff);
else
f = (jl_function_t*)ff;
assert(jl_is_function(f));
JL_TRY {
jl_apply(f, (jl_value_t**)&o, 1);
Expand All @@ -285,31 +288,36 @@ static void run_finalizer(jl_value_t *o, jl_value_t *ff)
jl_static_show(JL_STDERR, jl_exception_in_transit);
JL_PUTC('\n',JL_STDERR);
}
ff = jl_t1(ff);
}
f = (jl_function_t*)ff;
assert(jl_is_function(f));
JL_TRY {
jl_apply(f, (jl_value_t**)&o, 1);
if (jl_is_tuple(ff))
ff = jl_t1(ff);
else
break;
}
JL_CATCH {
JL_PRINTF(JL_STDERR, "error in running finalizer: ");
jl_static_show(JL_STDERR, jl_exception_in_transit);
JL_PUTC('\n',JL_STDERR);
}

static int finalize_object(jl_value_t *o)
{
jl_value_t *ff = NULL;
int success = 0;
JL_GC_PUSH1(&ff);
ff = (jl_value_t*)ptrhash_get(&finalizer_table, o);
if (ff != HT_NOTFOUND) {
ptrhash_remove(&finalizer_table, o);
run_finalizer((jl_value_t*)o, ff);
success = 1;
}
JL_GC_POP();
return success;
}

static void run_finalizers(void)
{
void *o = NULL;
jl_value_t *ff = NULL;
JL_GC_PUSH2(&o, &ff);
JL_GC_PUSH1(&o);
while (to_finalize.len > 0) {
o = arraylist_pop(&to_finalize);
ff = (jl_value_t*)ptrhash_get(&finalizer_table, o);
assert(ff != HT_NOTFOUND);
ptrhash_remove(&finalizer_table, o);
run_finalizer((jl_value_t*)o, ff);
int ok = finalize_object(o);
assert(ok); (void)ok;
}
JL_GC_POP();
}
Expand All @@ -336,6 +344,11 @@ void jl_gc_add_finalizer(jl_value_t *v, jl_function_t *f)
}
}

void jl_finalize(jl_value_t *o)
{
(void)finalize_object(o);
}

// big value list

static bigval_t *big_objects = NULL;
Expand Down
1 change: 1 addition & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,7 @@ void jl_gc_preserve(jl_value_t *v);
void jl_gc_unpreserve(void);
int jl_gc_n_preserved_values(void);
DLLEXPORT void jl_gc_add_finalizer(jl_value_t *v, jl_function_t *f);
DLLEXPORT void jl_finalize(jl_value_t *o);
DLLEXPORT jl_weakref_t *jl_gc_new_weakref(jl_value_t *value);
void *jl_gc_managed_malloc(size_t sz);
void *jl_gc_managed_realloc(void *d, size_t sz, size_t oldsz, int isaligned);
Expand Down
12 changes: 12 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,18 @@ begin
@test glo == 18
end

# finalizers
let
A = [1]
x = 0
finalizer(A, a->(x+=1))
finalize(A)
@test x == 1
A = 0
gc(); gc()
@test x == 1
end

# issue #7307
function test7307(a, ret)
try
Expand Down

1 comment on commit 2df759a

@StefanKarpinski
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handy.

Please sign in to comment.