Should go in manual but here is good for now.

As you know Felix runs a (rather lame) garbage collector.

It uses a shape object (rtti) to determine the size of an object and where
all the pointers are. The shape handles static arrays with a count.

Dynamic arrays are handled by an externally held per object count
of used entries, and another for the maximum. These two counts allow
an ordinary C pointer to be correctly scanned. The data structure that does
this is called a varray. It is special because it has core support.
In principle all data structures are varrays.

The gc has attached to it a set of roots. When collection is to be done,
all threads are intercepted at the next service call and frozen. The collection
has to wait for this, it's a design problem. [We may add Linux SIGSTOP support
to fix this on Linux, it can't be helped on other OS]

When the world has finally stopped, the stacks of all the threads are
added as roots, considered as pointer arrays. Therefore the stacks
are conservatively scanned, whilst everything else is exactly scanned.

The roots attached to the gc object use an STL map with a root count.

Rooting a pointer is used as a method by the async system. When a request
is queued for servicing, the fthread's root count is increments (usually from 0 
to 1).
This ensures the sleeping fthread is not deleted. With schannels, this is not 
done:
instead the fthread (fibre) is just attached to the schannel. The fibre will be
reaped if there are no other references and the schannel is unreachable.
This is what prevents fibres deadlocking: when they're dead(locked) they're
buried (reaped) so they no longer exist and therefore can't be in a deadlock
state -- true "in vaccuuo" :)

Felix supports "arbitrary" data structures as well. These are supported by
a custom scanner that finds the pointers. Judy is supported this way.
You can write a scanner for any type .. I'm doing one now for a bound queue,
which, underneath, is an STL queue<void*>. Note: you can NOT write scanners
for polymorphic data structures. What I mean is, the scanner would itself
be polymorphic. At present, Felix 

        requires scanner "function_name"

requires a non-polymorphic scanner. You can also supply a finaliser
if the default one, which is just a C++ destructor call, is not right.
This is needed for any object type, i.e. a non-mobile heap allocated
object represented by a pointer.

SO .. now we're looking into the future  a bit. But first a recap:

Felix uses a reference counted roots set + garbage collection
for automatic memory management, including finalisation by
executing C++ destructors (eg C++ string class uses dtor to release
the underlying char array).

So, if you have a C function that returns a pointer it allocated,
such as the usual "strdup" function, normally you are responsible
for free-ing it. Furthermore, any such data structure will not be scanned
for containing pointers. There are ways to fix this up for types you're
modelling and have control over allocation.

But now, there are ways to make Felix manage that C pointer.
instead of free-ing it, you can just convert it to a varray by telling
Felix its address, its type, and how long it is. [The API for doing this
may not exist yet .. that's the point of this note! ]

Now, suppose you have a Felix pointer and you want to lend it to 
a C function. As long as it is stored somewhere in Felix memory,
you can just do this.  But what if you're not retaining a copy?

You have two choices. First, you can just increment the pointers 
root count, and Felix won't delete it. When you get the pointer back,
you have to remember to decrement the count!

The second way is to release control of the pointer entirely, and re-acquire it
on return. Again: there's no API for this yet.

If the function is taking over the pointer, then you have to use the release 
technique.
Note that releasing a pointer to a buffer is fine, but releasing a pointer to 
an array
containing felix pointer is NOT OK. If you have to do that, you have to 
increment
the root count of the contained pointers, otherwise Felix may delete the objects
thinking they're unreachable, whilst C is holding them. [Note: we're usually 
talking
about callbacks here, but not always: don't forget Felix is multi-threaded so 
even whilst a C function is calculating stuff with the pointers, another thread 
might
be running. In theory the GC cannot be called at this time, but still, its a 
risk,
and this doesn't apply to callbacks where the C function stashes the pointer
somewhere hidden]

There's probably more. Note important point: Felix refcounts are *external*
to the object. So any object can be ref-counted. The STL map is probably going
away, it will be replaced by Judy. (The nice thing .. it suffices to actually 
root
the Judy array, there's no need for all the pointers contained in it to be
considered roots, since they're reachable via the Judy array anyhow .:)

On an unrelated note: at present, Felix suffers from NULL pointers.
I promise .. this is GOING AWAY! Core pointers will never be allowed to be NULL.
Instead, we'll just use a standard option type thingo, like:

        maybe_null_pointer[T] = NULL | Pointer of &T

which will FORCE the user to check for null. Note hat you can write

        let Pointer ?nnp = mnp in ... 

and a match failure will catch the Null pointer case.

 What is holding this up is the representation. At present, we get a 0 for the 
first
case, and a pointer with a 1 bit set in bit 0 for a pointer TO the pointer.
The actual pointer is heap allocated. This is no good! I need a representation
where any non-zero value indicates the second case (without the 1 bit,
and the pointer, not a pointer to a pointer), otherwise the representation
used in Felix will not be compatible with C.

There's another issue: incrementing pointer. Again, core pointers should not
be incrementable, at least not past the end of the varray they denote
(varrays are the core array kind, and the indexing and pointer increments
can be checked by the run time if we want, though the 1 past the end thing
is a real pain!)

Crudely, we don't need to use pointers for arrays at all: the base pointer
plus the index is quite good enough.

YMMV. Thanks for trolling along with me :)

--
john skaller
skal...@users.sourceforge.net





------------------------------------------------------------------------------
Virtualization & Cloud Management Using Capacity Planning
Cloud computing makes use of virtualization - but cloud computing 
also focuses on allowing computing to be delivered as a service.
http://www.accelacomm.com/jaw/sfnl/114/51521223/
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to