On Tuesday 13 November 2001 06:37 pm, James Mastros wrote:
> On Tue, Nov 13, 2001 at 06:14:30PM -0500, Michael L Maraist wrote:
> > Extending mem-mngr data-structures (like the linked-list) to the
> > definition of a PMC is what I'm worried about; not exposing a function to
> > say GC-me-more-often. (I appologize for the LISP mneumonic :)
>
> Hm. I think that the problem is that the definition of a PMC is, I think,
> what we say it is in perlpmc.pod, and not what we say it is in pmc.h.
>
> This means that we need to recomple XSes to change PMCs, but I think that's
> possibly OK. If not, why do we need to keep the linked-list inside the
> PMCs, instead of sepperatly?
Again, this is only speculation about possible algorithms. The only reason
to expose linked-list structures is if a collection algorithm was used that
assumed it contained a list of ALL PMCs. If the newPMC() / newPMCext() were
exclusively used, then this isn't a problem, but if PMC's could be externally
allocated and then registered within "foreign access", then there'd
potentially be a data-type mismatch. Namely using
header = (gc_object_header*)((int*)pmc_ptr - 2 )
header->next =...
header->prev=...
would be a failed assumption. I'm in favor of requiring newXX() since this
is more portable between memory managers.
It's equivalent to assuming that you could determine the size of a malloc'd
object by doing: *((int*)ptr - 1) simply because your current mem-mngr
stores the value there. Obviously it's best to pass the pointer to the
associated mem-mngr API and let it do things like fetching size. Here the
potential problem is static allocations generated by XS-code. In theory our
API would allow:
// desirable API functions
PMC_t* newPMC(); // assumes it'll be attached to the root-set
PMC_t* newPMCext(); // auto-ataches to "foreign access" portion of root-set.
void PL_registerForeignAccess(PMC_t*);
// questionable API function
void PL_unregisterForeignAccess(PMC_t*);
void PL_initPMC(PMC_t*);
And an XS coder could have:
void fooExtension(..) {
PMC_t my_pmc;
PL_initPMC( &my_pmc );
PL_registerForeignAccess( &my_pmc );
...
// my_pmc falls out of scope.
// coder forgot to call PL_unregisterFA( &my_pmc ); memory leak..
}
How PL_registerFA works isn't yet determined. If newPMCext() called
PL_regFA(), then there'd have to be some additional data-structure or
allocated memory. But if newPMCext() simply used the GC-exclusive region of
the linked-list, then the PMC could be placed on the appropriate list, and
thus avoid additional flags or memory allocations. It's state / type is
implicit based on the associated list as far as GCing is concerned. It's
just that this doesn't work with the above code.. The GC-hidden
data-structure could also have a ref-count of the number of times it's been
marked with PL_regFA, that way an intial reg-stack PMC could be grabbed by
XS-code and cached for what-ever evil purposes safely. Thus my current idea
of PMC handles is:
struct gc_handle_header_t {
struct gc_handle_header_t *prev, *next;
int fa_cnt;
char data[0]; // gcc-specific code for demonstration purposes
};
Again, this is just the weeding out stage.
-Michael