Revision 2029f0eb6ccd57468ba64b629d8ab2b5a8ddb80b authored by Rene Brun on 14 March 2004, 18:15:47 UTC, committed by Rene Brun on 14 March 2004, 18:15:47 UTC
for the case kExpo (shift by 1 in the use of parameters) git-svn-id: http://root.cern.ch/svn/root/trunk@8400 27541ba8-7e3a-0410-8455-c3a389f83636
1 parent 4c44cc3
gcoll.c
/* /% C %/ */
/***********************************************************************
* cint (C/C++ interpreter)
************************************************************************
* Source file gcoll.c
************************************************************************
* Description:
* Garbage Collection library and dictionary rewinding
************************************************************************
* Copyright(c) 1995~1999 Masaharu Goto
*
* Permission to use, copy, modify and distribute this software and its
* documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. The author makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
************************************************************************/
#include "common.h"
#define G__IMMEDIATE_GARBAGECOLLECTION
/**************************************************************************
* Garbage collection library usage
*
* G__init_garbagecollection();
*
* T *a = malloc(sizeof(T));
* G__add_alloctable(a,'u',G__defined_tagnum("T"));
* G__add_refcount(a,&a);
*
* T *b=a;
* G__add_refcount(b,&b);
*
* G__del_refcount(b,&b);
* b=NULL;
*
* G__del_alloctable(a);
* free((void*)a);
*
* G__garbagecollection();
*
*
**************************************************************************/
#define G__MAXREFTABLE 5
#define G__MAXALLOCTABLE 50
struct G__reflist {
void **ref;
struct G__reflist *prev;
struct G__reflist *next;
};
struct G__alloclist {
void *allocedmem;
char type;
short tagnum;
struct G__reflist *reflist;
struct G__alloclist *prev;
struct G__alloclist *next;
};
static struct G__alloclist *G__alloctable;
static struct G__alloclist *G__p_alloc;
static unsigned int G__count_garbagecollection;
/**************************************************************************
* Static functions
*
*
**************************************************************************/
/**************************************************************************
* G__search_alloctable()
**************************************************************************/
static struct G__alloclist* G__search_alloctable(mem)
void *mem;
{
struct G__alloclist *alloc;
alloc = G__alloctable;
while(alloc) {
if(mem==alloc->allocedmem) return(alloc);
alloc=alloc->next;
}
return((struct G__alloclist*)NULL);
}
/**************************************************************************
* G__free_reflist()
**************************************************************************/
static void G__free_reflist(reflist)
struct G__reflist *reflist;
{
if(reflist) {
if(reflist->next) {
G__free_reflist(reflist->next);
}
if(reflist->ref) *reflist->ref=(void*)NULL;
free((void*)reflist);
}
}
/**************************************************************************
* G__delete_reflist()
*
* 1) delete entry from alloclist
*
**************************************************************************/
static struct G__reflist* G__delete_reflist(alloc,reflist)
struct G__alloclist *alloc;
struct G__reflist *reflist;
{
struct G__reflist *freed;
static struct G__reflist temp;
if(reflist->prev) {
freed=reflist;
reflist->prev->next = reflist->next;
if(reflist->next) reflist->next->prev=reflist->prev;
reflist = reflist->prev;
}
else {
freed=reflist;
alloc->reflist = reflist->next;
if(alloc->reflist) alloc->reflist->prev=(struct G__reflist*)NULL;
temp.next = alloc->reflist;
reflist = &temp;
}
free((void*)freed);
return(reflist);
}
/**************************************************************************
* G__delete_alloctable()
*
* 1) delete entry from alloclist
*
**************************************************************************/
static struct G__alloclist* G__delete_alloctable(alloc)
struct G__alloclist *alloc;
{
struct G__alloclist *freed;
static struct G__alloclist temp;
if(!alloc->next) {
G__p_alloc = alloc->prev;
}
if(alloc->prev) {
freed=alloc;
alloc->prev->next = alloc->next;
if(alloc->next) alloc->next->prev=alloc->prev;
alloc = alloc->prev;
}
else {
freed=alloc;
G__alloctable = alloc->next;
if(G__alloctable) G__alloctable->prev=(struct G__alloclist*)NULL;
temp.next = G__alloctable;
alloc = &temp;
}
free((void*)freed);
return(alloc);
}
/**************************************************************************
* G__destroy_garbageobject()
*
* 1) If class object call destructor
* 2) If interpreted class or fundamental class, free memory or close file
*
**************************************************************************/
void G__destroy_garbageobject(alloc)
struct G__alloclist *alloc;
{
long store_tagnum;
long store_struct_offset;
long store_globalvarpointer;
int done=0;
char dtor[G__ONELINE];
if(-1!=alloc->tagnum) {
/* Call destructor if class object */
sprintf(dtor,"~%s()",G__struct.name[alloc->tagnum]);
store_globalvarpointer = G__globalvarpointer;
store_tagnum = G__tagnum;
store_struct_offset = G__store_struct_offset;
G__tagnum = alloc->tagnum;
G__store_struct_offset = (long)alloc->allocedmem;
if(G__CPPLINK==G__struct.iscpplink[alloc->tagnum]) {
G__globalvarpointer = G__store_struct_offset;
}
else {
G__globalvarpointer = G__PVOID;
}
G__getfunction(dtor,&done ,G__TRYDESTRUCTOR);
G__tagnum = store_tagnum;
G__store_struct_offset = store_struct_offset;
G__globalvarpointer = store_globalvarpointer;
if(G__CPPLINK!=G__struct.iscpplink[alloc->tagnum]) {
/* free resource , interpreted class */
free((void*)alloc->allocedmem);
}
}
else {
/* Fundamental type, free resource */
if('E'==alloc->type) {
fclose((FILE*)alloc->allocedmem);
}
else {
free((void*)alloc->allocedmem);
}
}
/* delete entry from alloclist */
/* alloc=G__delete_alloctable(alloc); */
/* increment garbage collection count */
++G__count_garbagecollection;
}
/**************************************************************************
* Exported functions
*
*
**************************************************************************/
/**************************************************************************
* G__init_garbagecollection()
**************************************************************************/
void G__init_garbagecollection()
{
static int state=1;
if(state) {
G__alloctable=(struct G__alloclist*)NULL;;
G__p_alloc = G__alloctable;
G__count_garbagecollection=0;
state=0;
}
}
/**************************************************************************
* G__garbagecollection()
**************************************************************************/
int G__garbagecollection()
{
struct G__alloclist *alloc;
struct G__reflist *reflist;
unsigned int count;
#ifndef G__IMMEDIATE_GARBAGECOLLECTION
G__fprinterr(G__serr,"!!! Reference Count Control start !!!\n");
#endif
alloc = G__alloctable;
while(alloc) {
if(!alloc->reflist) {
/* This object has no reference, means stray pointer */
G__destroy_garbageobject(alloc);
alloc=G__delete_alloctable(alloc);
}
else {
/* Delete dummy reference count for returned pointer */
reflist = alloc->reflist;
while(reflist) {
if((void**)NULL==reflist->ref) {
reflist=G__delete_reflist(alloc,reflist);
}
reflist=reflist->next;
}
}
alloc=alloc->next;
}
G__fprinterr(G__serr,"!!! %d object(s) deleted by Reference Count Control !!!\n"
,G__count_garbagecollection);
count = G__count_garbagecollection;
G__count_garbagecollection=0;
return(count);
}
/**************************************************************************
* G__add_alloctable()
**************************************************************************/
void G__add_alloctable(allocedmem,type,tagnum)
void *allocedmem;
int type;
int tagnum;
{
if(G__p_alloc) {
G__p_alloc->next=(struct G__alloclist*)malloc(sizeof(struct G__alloclist));
G__p_alloc->next->prev = G__p_alloc;
G__p_alloc=G__p_alloc->next;
}
else {
G__alloctable=(struct G__alloclist*)malloc(sizeof(struct G__alloclist));
G__p_alloc = G__alloctable;
G__p_alloc->prev =(struct G__alloclist*)NULL;
}
G__p_alloc->allocedmem = allocedmem;
G__p_alloc->type = (char)type;
G__p_alloc->tagnum = (short) tagnum;
G__p_alloc->reflist=(struct G__reflist*)NULL;
G__p_alloc->next=(struct G__alloclist*)NULL;
}
/**************************************************************************
* G__del_alloctable()
**************************************************************************/
int G__del_alloctable(allocmem)
void *allocmem;
{
struct G__alloclist *alloc;
alloc = G__search_alloctable(allocmem);
if(alloc) {
G__free_reflist(alloc->reflist);
G__delete_alloctable(alloc);
return(0);
}
else {
#ifndef G__FONS31
G__fprinterr(G__serr,"Error: Can not free 0x%lx, not allocated."
,(long)allocmem);
#else
G__fprinterr(G__serr,"Error: Can not free 0x%x, not allocated.",allocmem);
#endif
G__genericerror((char*)NULL);
return(1);
}
}
/**************************************************************************
* G__add_refcount()
**************************************************************************/
int G__add_refcount(allocedmem,storedmem)
void *allocedmem;
void **storedmem;
{
struct G__alloclist *alloc;
struct G__reflist *reflist;
alloc = G__search_alloctable(allocedmem);
if(alloc) {
if(alloc->reflist) {
reflist=alloc->reflist;
while(reflist->next) reflist=reflist->next;
reflist->next=(struct G__reflist*)malloc(sizeof(struct G__reflist));
reflist->next->prev=reflist;
reflist=reflist->next;
reflist->next=(struct G__reflist*)NULL;
reflist->ref=storedmem;
}
else {
alloc->reflist=(struct G__reflist*)malloc(sizeof(struct G__reflist));
reflist = alloc->reflist;
reflist->prev=(struct G__reflist*)NULL;
reflist->next=(struct G__reflist*)NULL;
reflist->ref=storedmem;
}
}
return(0);
}
/**************************************************************************
* G__del_refcount()
**************************************************************************/
int G__del_refcount(allocedmem,storedmem)
void *allocedmem;
void **storedmem;
{
int flag=1;
struct G__alloclist *alloc;
struct G__reflist *reflist;
alloc = G__search_alloctable(allocedmem);
if(alloc) {
reflist = alloc->reflist;
while(reflist) {
if(reflist->ref==storedmem) {
reflist=G__delete_reflist(alloc,reflist);
}
else if((void**)NULL==reflist->ref) {
reflist=G__delete_reflist(alloc,reflist);
flag=0;
}
reflist=reflist->next;
}
#ifdef G__IMMEDIATE_GARBAGECOLLECTION
if(!alloc->reflist && flag) {
#ifdef G__DEBUG
#ifndef G__OLDIMPLEMENTATION401
G__fprinterr(G__serr,"!!! %s object deleted by Reference Count Control !!!\n"
,G__type2string(alloc->type,alloc->tagnum,-1,0,0));
#else
G__fprinterr(G__serr,"!!! %s object deleted by Reference Count Control !!!\n"
,G__type2string(alloc->type,alloc->tagnum,-1,0));
#endif
#endif
G__destroy_garbageobject(alloc);
G__delete_alloctable(alloc);
}
#endif
}
return(0);
}
/**************************************************************************
* Debugging functions
*
*
**************************************************************************/
/**************************************************************************
* G__disp_garbagecollection()
**************************************************************************/
int G__disp_garbagecollection(fout)
FILE *fout;
{
static struct G__alloclist *alloc;
struct G__reflist *reflist;
alloc = G__alloctable;
fprintf(fout,"Allocated memory =========================================\n");
fprintf(fout,"type : location : reference(s)\n");
while(alloc) {
#ifndef G__OLDIMPLEMENTATION401
fprintf(fout,"%-20s: 0x%lx :"
,G__type2string(alloc->type,alloc->tagnum,-1,0,0)
,(long)alloc->allocedmem);
#else
fprintf(fout,"%-20s: 0x%lx :"
,G__type2string(alloc->type,alloc->tagnum,-1,0)
,alloc->allocedmem);
#endif
reflist = alloc->reflist;
while(reflist) {
#ifndef G__FONS31
fprintf(fout," 0x%lx ,",(long)reflist->ref);
#else
fprintf(fout," 0x%x ,",reflist->ref);
#endif
reflist = reflist->next;
}
fprintf(fout,"\n");
alloc=alloc->next;
}
return(0);
}
/*
* Local Variables:
* c-tab-always-indent:nil
* c-indent-level:2
* c-continued-statement-offset:2
* c-brace-offset:-2
* c-brace-imaginary-offset:0
* c-argdecl-indent:0
* c-label-offset:-2
* compile-command:"make -k"
* End:
*/
Computing file changes ...