PureBasic, and so far it seems to work nicely.
Anyone is free to do his own tests. I'm running
on Ubuntu 11.10 x64. Would be nice to know
if the include is compatible with 32 bit.
It's very easy to allocate memory and to register
a finalizer which can do the cleanup when the
memory is not referenced anymore.
Using this include it should be straightforward to
create garbage-collected libraries in PB where
you don't have to call Free*() anymore.
Here is a small example allocating ~1GB of memory
in 1MB blocks that trigger the GC ~400 times on
my machine:
Code: Select all
XIncludeFile "boehm.pbi"
GC_init()
ProcedureC finalizer(*obj, *client_data)
Debug Str(ElapsedMilliseconds()) + " : free " + Str(*client_data)
EndProcedure
For i = 0 To 999
*a = GC_MALLOC_(1024*1024) ; 1 MB
Debug Str(ElapsedMilliseconds()) + " : alloc " + Str(i)
GC_REGISTER_FINALIZER_(*a, @finalizer(), i, 0, 0)
Next
msg.s = "GC runs: "+Str(GC_gc_no)+#LF$
msg + "Heap size (KB): "+Str(GC_get_heap_size() / 1024)+#LF$
msg + "Free bytes (KB): "+Str(GC_get_free_bytes() / 1024)+#LF$
msg + "Bytes since last collection (KB): "+Str(GC_get_bytes_since_gc() / 1024)+#LF$
msg + "Total allocated bytes (KB): "+Str(GC_get_total_bytes() / 1024)+#LF$
MessageRequester("Stop", msg)

Documentation: http://www.hpl.hp.com/personal/Hans_Boe ... rface.html
Cheers,
Remi
boehm.pbi
Code: Select all
; /*
; * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
; * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
; * Copyright 1996-1999 by Silicon Graphics. All rights reserved.
; * Copyright 1999 by Hewlett-Packard Company. All rights reserved.
; *
; * THIS MATERIAL IS PROVIDED As IS, With ABSOLUTELY NO WARRANTY EXPRESSED
; * Or IMPLIED. ANY USE IS AT YOUR OWN RISK.
; *
; * Permission is hereby granted To use Or copy this program
; * For any purpose, provided the above notices are retained on all copies.
; * Permission To modify the code And To distribute modified code is granted,
; * provided the above notices are retained, And a notice that the code was
; * modified is included With the above copyright notice.
; */
; GC_word = ptr
; GC_signed_word = int
PrototypeC.i GC_OOM_FN(bytes_requested.i)
PrototypeC GC_FINALIZER_NOTIFIER()
PrototypeC GC_FINALIZATION_PROC(*obj, *client_data)
Structure GC_FINALIZATION_PROC_STRUCT
ofn.GC_FINALIZATION_PROC
EndStructure
#GC_TIME_UNLIMITED = 999999
#GC_PROTECTS_POINTER_HEAP = 1
#GC_PROTECTS_PTRFREE_HEAP = 2
#GC_PROTECTS_STATIC_DATA = 4
#GC_PROTECTS_STACK = 8
#GC_PROTECTS_NONE = 0
ImportC "-lgc"
GC_gc_no.i
GC_parallel.l
GC_oom_fn.GC_OOM_FN
GC_find_leak.l
GC_all_interior_pointers.l
GC_quiet.l
GC_finalize_on_demand.l
GC_java_finalization.l
GC_finalizer_notifier.GC_FINALIZER_NOTIFIER
GC_dont_gc.l
GC_dont_expand.l
GC_use_entire_heap.l
GC_full_freq.l
GC_non_gc_bytes.i
GC_no_dls.l
GC_free_space_divisor.i
GC_max_retries.i
*GC_stackbottom
GC_dont_precollect.l
GC_time_limit.i
;/* Public procedures */
GC_init()
GC_malloc.i(size_in_bytes.i)
GC_malloc_atomic.i(size_in_bytes.i)
GC_malloc_uncollectable.i(size_in_bytes.i)
GC_malloc_stubborn.i(size_in_bytes.i)
GC_free(*object_addr)
GC_change_stubborn(*ptr)
GC_end_stubborn_change(*ptr)
GC_base.i(*displaced_ptr)
GC_size.i(*object_addr)
GC_realloc.i(*old_obj, new_size_in_bytes.i)
GC_expand_hp.l(number_of_bytes.i)
GC_set_max_heap_size(n.i)
GC_exclude_static_roots(*start, *finish)
GC_register_displacement(n.i)
GC_debug_register_displacement(n.i)
GC_gcollect()
GC_get_heap_size.i()
GC_get_free_bytes.i()
GC_get_bytes_since_gc.i()
GC_get_total_bytes.i()
GC_disable()
GC_enable()
GC_enable_incremental()
GC_incremental_protection_needs.l()
GC_collect_a_little.l()
GC_malloc_ignore_off_page.i(lb.i)
GC_malloc_atomic_ignore_off_page.i(lb.i)
GC_debug_malloc.i(size_in_bytes.i, s.p-ascii, i.l)
GC_debug_malloc_atomic.i(size_in_bytes.i, s.p-ascii, i.l)
GC_debug_malloc_uncollectable.i(size_in_bytes.i, s.p-ascii, i.l)
GC_debug_malloc_stubborn.i(size_in_bytes.i, s.p-ascii, i.l)
GC_debug_malloc_ignore_off_page.i(size_in_bytes.i, s.p-ascii, i.l)
GC_debug_malloc_atomic_ignore_off_page.i(size_in_bytes.i, s.p-ascii, i.l)
GC_debug_free(*object_addr)
GC_debug_realloc.i(*old_object, new_size_in_bytes.i, s.p-ascii, i.l)
GC_debug_change_stubborn(*addr)
GC_debug_end_stubborn_change(*addr)
GC_debug_malloc_replacement.i(size_in_bytes.i)
GC_debug_realloc_replacement.i(*object_addr, size_in_bytes.i)
GC_register_finalizer(*obj, fn.GC_FINALIZATION_PROC, *cd, *ofn.GC_FINALIZATION_PROC_STRUCT, *ocd.INTEGER)
GC_debug_register_finalizer(*obj, fn.GC_FINALIZATION_PROC, *cd, *ofn.GC_FINALIZATION_PROC_STRUCT, *ocd.INTEGER)
GC_register_finalizer_ignore_self(*obj, fn.GC_FINALIZATION_PROC, *cd, *ofn.GC_FINALIZATION_PROC_STRUCT, *ocd.INTEGER)
GC_debug_register_finalizer_ignore_self(*obj, fn.GC_FINALIZATION_PROC, *cd, *ofn.GC_FINALIZATION_PROC_STRUCT, *ocd.INTEGER)
GC_register_disappearing_link.l(*link)
GC_general_register_disappearing_link.l(*link, *obj)
GC_unregister_disappearing_link.l(*link)
GC_should_invoke_finalizers.l()
GC_invoke_finalizers.l()
GC_set_free_space_divisor.i(value.i)
; thread stuff
GC_pthread_create.l(*new_thread, *attr, *proc, *arg)
GC_pthread_join.l(*thread, *retval)
GC_pthread_detach.l(*thread)
EndImport
CompilerIf Defined(GC_DEBUG, #PB_Constant)
Macro GC_EXTRAS : "", #PB_Compiler_Line : EndMacro
Macro GC_MALLOC_(sz) : GC_debug_malloc(sz, GC_EXTRAS) : EndMacro
Macro GC_MALLOC_ATOMIC_(sz) : GC_debug_malloc_atomic(sz, GC_EXTRAS) : EndMacro
Macro GC_MALLOC_UNCOLLECTABLE_(sz) : GC_debug_malloc_uncollectable(sz, GC_EXTRAS) : EndMacro
Macro GC_MALLOC_IGNORE_OFF_PAGE_(sz) : GC_debug_malloc_ignore_off_page(sz, GC_EXTRAS) : EndMacro
Macro GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE_(sz) : GC_debug_malloc_atomic_ignore_off_page(sz, GC_EXTRAS) : EndMacro
Macro GC_REALLOC_(old, sz) : GC_debug_realloc(old, sz, GC_EXTRAS) : EndMacro
Macro GC_FREE_(p) : GC_debug_free(p) : EndMacro
Macro GC_REGISTER_FINALIZER_(p, f, d, of, od) : GC_debug_register_finalizer(p, f, d, of, od) : EndMacro
Macro GC_REGISTER_FINALIZER_IGNORE_SELF_(p, f, d, of, od) : GC_debug_register_finalizer_ignore_self(p, f, d, of, od) : EndMacro
Macro GC_REGISTER_FINALIZER_NO_ORDER_(p, f, d, of, od) : GC_debug_register_finalizer_no_order(p, f, d, of, od) : EndMacro
Macro GC_MALLOC_STUBBORN_(sz) : GC_debug_malloc_stubborn(sz, GC_EXTRAS) : EndMacro
Macro GC_CHANGE_STUBBORN_(p) : GC_debug_change_stubborn(p) : EndMacro
Macro GC_END_STUBBORN_CHANGE_(p) : GC_debug_end_stubborn_change(p) : EndMacro
Macro GC_GENERAL_REGISTER_DISAPPEARING_LINK_(link, obj) : GC_general_register_disappearing_link(link, GC_base(obj)) : EndMacro
Macro GC_REGISTER_DISPLACEMENT_(n) : GC_debug_register_displacement(n) : EndMacro
CompilerElse
Macro GC_MALLOC_(sz) : GC_malloc(sz) : EndMacro
Macro GC_MALLOC_ATOMIC_(sz) : GC_malloc_atomic(sz) : EndMacro
Macro GC_MALLOC_UNCOLLECTABLE_(sz) : GC_malloc_uncollectable(sz) : EndMacro
Macro GC_MALLOC_IGNORE_OFF_PAGE_(sz) : GC_malloc_ignore_off_page(sz) : EndMacro
Macro GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE_(sz) : GC_malloc_atomic_ignore_off_page(sz) : EndMacro
Macro GC_REALLOC_(old, sz) : GC_realloc(old, sz) : EndMacro
Macro GC_FREE_(p) : GC_free(p) : EndMacro
Macro GC_REGISTER_FINALIZER_(p, f, d, of, od) : GC_register_finalizer(p, f, d, of, od) : EndMacro
Macro GC_REGISTER_FINALIZER_IGNORE_SELF_(p, f, d, of, od) : GC_register_finalizer_ignore_self(p, f, d, of, od) : EndMacro
Macro GC_REGISTER_FINALIZER_NO_ORDER_(p, f, d, of, od) : GC_register_finalizer_no_order(p, f, d, of, od) : EndMacro
Macro GC_MALLOC_STUBBORN_(sz) : GC_malloc_stubborn(sz) : EndMacro
Macro GC_CHANGE_STUBBORN_(p) : GC_change_stubborn(p) : EndMacro
Macro GC_END_STUBBORN_CHANGE_(p) : GC_end_stubborn_change(p) : EndMacro
Macro GC_GENERAL_REGISTER_DISAPPEARING_LINK_(link, obj) : GC_general_register_disappearing_link(link, obj) : EndMacro
Macro GC_REGISTER_DISPLACEMENT_(n) : GC_register_displacement(n) : EndMacro
CompilerEndIf