/** * A roll-you-own reference counting garbage collector * The idea here is that there is a struct (stringRC) that is used * by other structs (substringRC). Hence, it should only be freed when there * are no remaining users. It does this by have a counter to keep * rack of the number of users. * * So only a users cooperate, this works. * * @author gtowell * Created April 2021 * **/ #include #include #include typedef struct { char *string; int refCount; // the number of users int mainFreed; // true iff someone has called free on this struct // but it still has users } stringRC; // Users of the other struct typedef struct { stringRC* string; int strt; int len; } substringRC; /** * Constructor * **/ stringRC* makeStringRC(char * src) { stringRC *rc = malloc(1 * sizeof(stringRC)); rc->string = malloc((strlen(src)+1) * sizeof(char)); strcpy(rc->string, src); rc->refCount = 0; rc->mainFreed = 0; return rc; } /** * User constructor * Increments the reference count in the used struct * **/ substringRC* makeSubstringRC(stringRC* str, int st, int len) { substringRC *src = malloc(1 * sizeof(substringRC)); src->string = str; src->strt = st; src->len = len; str->refCount++; return src; } /** * Destroy the main struct. Only actually does the free-ing if there * are no users * **/ void freeStringRC(stringRC* str) { if (str->refCount==0) { printf("NO Refs -- freeing\n"); free(str->string); free(str); } else { printf("Not freeing -- still has refs [%d]\n", str->refCount); str->mainFreed = 1; } } /** * Destroy the user class (and decrement the reference count in the used class) * Checks the used class and will destroy it if the reference count == 0 * and it is maked for destruction * **/ void freeSubstringRC(substringRC* src) { stringRC *tmp = src->string; free(src); tmp->refCount--; if (tmp->refCount==0 && tmp->mainFreed) { freeStringRC(tmp); } } /** * Printer for the substring struct * **/ void printSubstr(substringRC* sstr) { for (int i = 0; i < sstr->len; i++) printf("%c", sstr->string->string[sstr->strt + i]); printf("\n"); } /** * Printer for the main struct * **/ void printString(stringRC *str) { printf("%s\n", str->string); } int main(int argc, char const *argv[]) { stringRC *rc = makeStringRC("now is the time of all good people to come to the aid of their country"); substringRC *src1 = makeSubstringRC(rc, 0, 5); printSubstr(src1); freeSubstringRC(src1); printString(rc); freeStringRC(rc); return 0; }