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