Gerbage collection as a library

V

Victor Nazarov

I've tried to implement some garbage collection library for see. Here is
an example of it's usage. Do you think that it is usefull at all and
deserve development?

#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include "virlib.h"

void fclose_p (void *p);
void print (fp);
char *readline (fp);

int
main (int argc, char **argv)
{
FILE *fp;
begin_func ();

fp = fopen ("style.txt", "r");
add_destructor (fp, fclose_p);

print (fp);

end_func ();
return 0;
}

void
fclose_p (void *p)
{
fclose (p);
}

void
print (fp)
{
char *s;
int n;

begin_func ();
n = 0;
while ((s = readline (fp)) != NULL)
fprintf ("%4d%s", n++, s);
end_func ();
}

char *
readline (fp)
{
char *s, *t, *p;
int alen, llen;

begin_func ();
alen = 10;
s = malloc (alen);
if (s == NULL)
fail ("allocating buffer to read");
add_destructor (s, free);

p = s;
for (;;) {
t = fgets (p, alen, fp);
if (t == NULL) {
end_func ();
return NULL;
}

llen = strlen (p);
if (p[llen - 1] == '\n') {
mark_result (s);
end_func ();
return s;
}

llen = p - s;
t = realloc (s, alen * 2);
if (t == NULL)
fail ("allocating buffer to read");
mark_global (s); /* No need to destruct s */
s = t;
add_destructor (s, free);
p = s + llen;
}
}
 
W

Walter Roberson

I've tried to implement some garbage collection library for see. Here is
an example of it's usage. Do you think that it is usefull at all and
deserve development?

[code snipped]

I would suggest that you describe each of the library operations and
their purpose.

It appears from your code example that the user needs to manually
add_destructor) each item which is to be garbage collected,
and to mark_global() each item which is not to be garbage collected.
The user also appears to need to begin_func(), and appears to need
to end_func() at the end before returning from your routine.

The operation of mark_result() is not clear from your example --
does it sort of move the pointer's destruction time into the frame
above? But if it does then if you are returning a pointer through
multiple layers, you would have to know to mark_result() the pointer
at each layer. What is the user to do if the user wants to
return a structure or array that mixes items which are to be have
destructors run and items which are not to have destructors run?


It is not apparent from your example why it is that you do not
have two operations:

1) add_destructor() to record that an item will need to be garbage collected.
return value: an internal marker of the current garbage collection stack.

2) gc() to trigger a garbage collection. The argument to this would
be one of the values returned by add_destructor(), and gc() would
do the destruction of everything back to that marker.

There is no obvious need in your scheme for mark_global() since if
something is not marked for destruction then it simply wouldn't be
destroyed. (I do not have advice at the moment as to how to
handle values that are going to be returned.)


In my -opinion-, your present interface has too much manual work and
coding overhead, and would not become popular.

char *
readline (fp)
{
char *s, *t, *p;
int alen, llen;

begin_func ();
alen = 10;
s = malloc (alen);
if (s == NULL)
fail ("allocating buffer to read");
add_destructor (s, free);

p = s;
for (;;) {
t = fgets (p, alen, fp);
if (t == NULL) {
end_func ();
return NULL;
}

llen = strlen (p);
if (p[llen - 1] == '\n') {
mark_result (s);
end_func ();
return s;
}

llen = p - s;
t = realloc (s, alen * 2);

After the realloc(), the former value of s is not certain
to be valid anymore. This implies that you would need an operation
which was "transfer the attributes associated with this pointer
to instead be associated with this other pointer".
if (t == NULL)
fail ("allocating buffer to read");
mark_global (s); /* No need to destruct s */

But the value of s is not valid anymore?? Unless this -is- your
way of saying, "remove the attributes that were associated with this
pointer" -- and then requiring the user to know what the attributes
were and to set them on the new pointer. It would be easier on
the user to have a realloc() wrapper that took care of these details.
 
V

Victor Nazarov

Walter said:
It appears from your code example that the user needs to manually
add_destructor) each item which is to be garbage collected,
and to mark_global() each item which is not to be garbage collected. yes

The user also appears to need to begin_func(), and appears to need
to end_func() at the end before returning from your routine. yes

The operation of mark_result() is not clear from your example --
does it sort of move the pointer's destruction time into the frame
above? yes

But if it does then if you are returning a pointer through
multiple layers, you would have to know to mark_result() the pointer
at each layer.
User must mark_result() every "object" that function returns. I think
it's not so difficult to know what are you returning.
What is the user to do if the user wants to
return a structure or array that mixes items which are to be have
destructors run and items which are not to have destructors run?
That's not solved yet. I think some routings should be written for
containers to implement their own resource managment. So if object is
added to an array it should be deleted when the array is deleted.
May be you can suggest something?
It is not apparent from your example why it is that you do not
have two operations:

1) add_destructor() to record that an item will need to be garbage collected.
return value: an internal marker of the current garbage collection stack.

2) gc() to trigger a garbage collection. The argument to this would
be one of the values returned by add_destructor(), and gc() would
do the destruction of everything back to that marker.
Hmm, it's impossible to implement it from user level, only compiler
level, isn't it? I'm just trying to add resource management to C, not
developing new language. There are Java and Caml after all.
There is no obvious need in your scheme for mark_global() since if
something is not marked for destruction then it simply wouldn't be
destroyed.
So it's used in the realloc example, i. e. "cancel managment of this
object, I'll do this manually".
(I do not have advice at the moment as to how to
handle values that are going to be returned.)


In my -opinion-, your present interface has too much manual work and
coding overhead, and would not become popular.
My interface shouldn't be used every where. That was the part of the
design. The question is "are there cases when this library whould be
much better then manual resource managment? and how often is this?".
After the realloc(), the former value of s is not certain
to be valid anymore. This implies that you would need an operation
which was "transfer the attributes associated with this pointer
to instead be associated with this other pointer".




But the value of s is not valid anymore?? Unless this -is- your
way of saying, "remove the attributes that were associated with this
pointer" -- and then requiring the user to know what the attributes
were and to set them on the new pointer.
Yes, that's what I've said.
It would be easier on
the user to have a realloc() wrapper that took care of these details.
Yes, it would.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,173
Messages
2,570,937
Members
47,481
Latest member
ElviraDoug

Latest Threads

Top