FreeBASIC Reference Counter (Hopefully a GC some day)

User contributed sources that have become inactive, deprecated, or generally unusable. But ... we don't really want to throw them away either.
Post Reply
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

FreeBASIC Reference Counter (Hopefully a GC some day)

Post by anonymous1337 »

Not yet a true garbage collector, but I'm working on it.

https://github.com/anonymous1337/FB-Garbage-Collector

Currently, there exists a GarbageCollector interface/mock class which behaves like normal Ctors/Dtors. A ReferenceCounter then implements/overrides it. A visitor-ish pattern is called whenever we have construction, destruction or assignment. This lets the GC decide when stuff is constructed, destructed or assigned.

A reference count is hard-coded in the reference type, but I think the ReferenceCounter GC is the only class that uses it, so it can probably be ignored by additional GCs until it's removed. Tbh, I just didn't want to bother making a DynamicArray class/macro just so the ReferenceCounter could store a list of references and how many external references to them there are.

Here's a demo:

Code: Select all

' Seems like everything can be included except this for now...
'#include "GarbageCollector.bi"
#include "ReferenceCounter.bi"
#include "Reference.bi"
#include "RInteger.bi"

#include "GarbageCollector.bas"
#include "ReferenceCounter.bas"
#include "Reference.bas"
#include "RInteger.bas"

#macro str_iif( c, t, f )
	*cast( zstring ptr, iif( c, @t, @f ))
#endmacro

#macro str_expr( c )
	str_iif( c, "true", "false" )
#endmacro

using anonymous1337.gc.core

' This default collector does nothing special.  Just prints what's going on.
dim as GarbageCollector default_collector
'garbage_collector = @default_collector

' For now, our most complex "garbage collector" is just a reference counter.
dim as ReferenceCounter reference_counter
garbage_collector = GarbageCollector.from(@reference_counter)

sub main()
 
	dim as RInteger my_age
	dim as RInteger your_age
	dim as RInteger our_age
	my_age = 23
	your_age = 23
	our_age = my_age
	
	print ""
	
	print "My age:  " & int(my_age)
	print "Your age:  " & int(your_age)
	print "Our age:  " & int(our_age)
	
	print ""
	
	print "My age type_id:  " & Reference.from(@my_age)->type_id
	print "Your age type_id:  " & Reference.from(@your_age)->type_id
	print "Our age type_id:  " & Reference.from(@our_age)->type_id
	
	print ""
	
	print "Do my_age and your_age have equal values?:  " & str_expr( my_age = your_age )
	print "Do my_age and your_age have equal reference values?:  " & str_expr( *Reference.from(@my_age) = *Reference.from(@your_age) )
	
	print ""
	
	print "Do our_age and my_age have equal values?:  " & str_expr( my_age = our_age )
	print "Do our_age and my_age have equal reference values?:  " & str_expr( *Reference.from(@my_age) = *Reference.from(@our_age) )
	
	print ""
	
	print "Do our_age and your_age have equal values?:  " & str_expr( your_age = our_age )
	print "Do our_age and your_age have equal reference values?:  " & str_expr( *Reference.from(@your_age) = *Reference.from(@our_age) )
	
	sleep
	
end sub

main()
sleep
Output:

Code: Select all

Constructed a reference with value:  0
Constructed a reference with value:  7673880
Constructed a reference with value:  0
Constructed a reference with value:  7673912
Constructed a reference with value:  0
Constructed a reference with value:  7677968
Assigned reference  1638108 to reference 1638044

My age:  23
Your age:  23
Our age:  23

My age type_id:  __RInteger
Your age type_id:  __RInteger
Our age type_id:  __RInteger

Do my_age and your_age have equal values?:  true
Do my_age and your_age have equal reference values?:  false

Do our_age and my_age have equal values?:  true
Do our_age and my_age have equal reference values?:  true

Do our_age and your_age have equal values?:  true
Do our_age and your_age have equal reference values?:  false
Destructed a reference with value:  7673880
Destructed a reference with value:  7673880
Destructed a reference with value:  7673912
Destructed a reference with value:  7673912
Destructed a reference with value:  7673880
Destructed a reference with value:  7673880
So I wanted to hold off on showing this until it was complete, but:

1) I only get to work on this during the weekends because I am fully employed.
2) It's already been a couple weeks and I'm getting impatient.
3) FB's had some feature additions/changes since I last updated and I don't want my time to be wasted.
4) I don't know much about garbage collection yet. I've essentially brought to you pseudo-smart pointers. Enjoy.
AGS
Posts: 1284
Joined: Sep 25, 2007 0:26
Location: the Netherlands

Re: FreeBASIC Reference Counter (Hopefully a GC some day)

Post by AGS »

If you look at garbage collectors available for compiler languages then there is only one
publicly available garbage collector: the Boehm-Demers-Weiser garbage collector.
This collector
- does not work on all versions of windows 7;
- is part of the gcc source repository;
- is at the base of quite a few other garbage collectors.

You can already use the BDW-collector in combination with freebasic if you stay away from
the OOP features of freebasic. Just replace calls to callocate, allocate and reallocate with
calls to GC_CALLOC, GC_MALLOC, GC_REALLOC and you're done. You might (or might not)
have to recompile the fb runtime library but the BDW-collector should not interfere with C code
that does manual garbage collection.

A possible source repository for the BDW garbage collector (it gets updated on a regular base):
https://github.com/ivmai/bdwgc/
or from gcc
http://gcc.gnu.org/viewcvs/trunk/boehm-gc/

And a link to a page on garbage collection in mono (open source version of .NET):
http://www.mono-project.com/Generational_GC

Another interesting project is Eiffel (programming language).
Source code available here:
https://svn.eiffel.com/eiffelstudio/trunk/

and the garbage collector it utilizes is at
https://svn.eiffel.com/eiffelstudio/tru ... e/garcol.c

Eiffel produces C code (or il or java bytecode or ....). Eiffel has been around
for ages and I think (hope) the people developing Eiffel know how to write a
good garbage collector.

Another eiffel implementation, smarteiffel, produces C code and implements
it's own collector. You can find the code on GitHub
https://github.com/berenddeboer/smartei ... /runtime/c
or at the original site
https://gforge.inria.fr/scm/viewvc.php/ ... marteiffel

I don't think the smarteiffel code is as good as the code found at svn.eiffel.com.

Runtime impact of garbage collection is not too bad (although memory usage does tend
to go up considerably). If you look at interpreted languages there are languages that
use garbage collection (lua and others). And there are interpreted languages that
use reference counting (python and others). It is not so that the languages that
use garbage collection are 'slower' than the ones using reference counting.

The D programming language uses a garbage collector as well
https://github.com/D-Programming-Langua ... c/gc/gcx.d

Interesting things, garbage collectors. Pity it's so hard to write a good one.
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Re: FreeBASIC Reference Counter (Hopefully a GC some day)

Post by anonymous1337 »

Great post, AGS. Exactly the kind of thing I was looking for.
Post Reply