Hey,

I found somehow confusing functionality of garbage collector,
which I really can't understand.
It seems to me, that gc calls the mark functions for garbage objects
before they are than correctly removed from memory.
Is it the a wanted action or some kind of side effect?

Roman

[init] child_tag = 0x1677
[init] container_tag = 0x1777
version = 2.2.0.18-d7778
(
[let begin] ----------------------------------------
[make_container] ptr=0x9b345fe0 (0x1777,0x9b296480)
[make_container] ptr=0x9b345fc0 (0x1777,0x9b296440)
[make_child] ptr=0x9b345fa0 (0x1677,0x4)
[make_child] ptr=0x9b345f80 (0x1677,0x4)
ch1 = #<child 0x9b345fa0>
ch2 = #<child 0x9b345f80>
c1 = #<container my.container.1 child=0x9b345fa0>
c2 = #<container my.container.2 child=0x9b345f80>
[mark_child] ptr=0x9b345f80 (0x1677,0x4)
[mark_child] ptr=0x9b345fa0 (0x1677,0x4)
[mark_container] ptr=0x9b345fc0 (0x1777,0x9b296440)
[mark_container] ptr=0x9b345fe0 (0x1777,0x9b296480)
[let end] ------------------------------------------
)

+----------------------------------------------------+
|  What are the following mark functions called for? |
+----------------------------------------------------+
[mark_child] ptr=0x9b345f80 (0x1677,0x4)
[mark_child] ptr=0x9b345fa0 (0x1677,0x4)
[mark_container] ptr=0x9b345fc0 (0x1777,0x9b296440)
[mark_container] ptr=0x9b345fe0 (0x1777,0x9b296480)
[free_child] ptr=0x9b345f80 (0x0077,0x4)
[free_child] ptr=0x9b345fa0 (0x0077,0x4)
[free_container] ptr=0x9b345fc0 (0x0077,0x9b296440)
[free_container] ptr=0x9b345fe0 (0x0077,0x9b296480)


//$.
#include <stdlib.h>
#include <libguile.h>

static scm_t_bits child_tag;

//__________________________________________________________________________________________________
//$. make_child ()
static SCM
make_child ()
{
	SCM smob;
	smob = scm_new_smob (child_tag, SCM_BOOL_F);
	fprintf (stderr, "[make_child] ptr=0x%x (0x%x,0x%x)\n",
			 (int)smob, (int)((void**)smob)[0], (int)((void**)smob)[1]);
	return smob;
}

//__________________________________________________________________________________________________
//$. mark_child ()
/* This function is responsible for marking all SCM objects included
 * in the smob. */
static SCM
mark_child (SCM child_smob)
{
	fprintf (stderr, "[mark_child] ptr=0x%x (0x%x,0x%x)\n",
			 (int)child_smob,
			 (int)((void**)child_smob)[0], (int)((void**)child_smob)[1]);
	/* we simply return child_smob and the caller will mark it. */
	return SCM_CELL_OBJECT_1 (child_smob);
}

//__________________________________________________________________________________________________
//$. free_child ()
static size_t
free_child (SCM child_smob)
{
	fprintf (stderr, "[free_child] ptr=%#x (%#06x,%#x)\n",
			 (int)child_smob,
			 (int)((void**)child_smob)[0], (int)((void**)child_smob)[1]);
	if (SCM_TYP7(child_smob) != (0xff & child_tag)) {
		// bad type, not dbi smob, do not free it
		fprintf (stderr, "[free] error: bad smob 0x%x\n", (int)SCM_TYP16(child_smob));
		return 0;
	}
	return 0;
}

//__________________________________________________________________________________________________
//$. print_child ()
static int
print_child (SCM child_smob, SCM port, scm_print_state* pstate)
{
	scm_puts ("#<child ", port);
	printf ("%#x", (int)child_smob); fflush(stdout);
	scm_puts (">", port);
	/* non-zero means success */
	return 1;
}

//__________________________________________________________________________________________________
//$. init_child_type()
void
init_child_type (void)
{
	child_tag = scm_make_smob_type ("box", 0);
	fprintf (stderr, "[init] child_tag = 0x%x\n", (int)child_tag);
	scm_set_smob_mark (child_tag, mark_child);
	scm_set_smob_free (child_tag, free_child);
	scm_set_smob_print (child_tag, print_child);
	scm_c_define_gsubr ("make-child", 0, 0, 0, make_child);
}

#if !defined (_CHILD_H_)
#define _CHILD_H_

void init_child_type (void);

#endif

//$.
#include <stdlib.h>
#include <libguile.h>
#include <child.h>

static scm_t_bits container_tag;

//__________________________________________________________________________________________________
//$. struct container
struct container
{
	/* char array */
	int array_length;
	char* array;
	/* The name of this container */
	SCM name;
	/* The child of this container */
	SCM child;
};

//__________________________________________________________________________________________________
//$. make_container ()
static SCM
make_container (SCM name, SCM s_length)
{
	SCM smob;
	struct container* container;
	int array_length = scm_to_int (s_length);

	/* Step 1: Allocate the memory block.
	 *   Memory blocks that are associated with Scheme objects (for example a
	 * foreign object) should be allocated with ‘scm_gc_malloc’ or
	 * ‘scm_gc_malloc_pointerless’.  These two functions will either return a
	 * valid pointer or signal an error.  Memory blocks allocated this way may
	 * be released explicitly; however, this is not strictly needed, and we
	 * recommend _not_ calling ‘scm_gc_free’.  All memory allocated with
	 * ‘scm_gc_malloc’ or ‘scm_gc_malloc_pointerless’ is automatically
	 * reclaimed when the garbage collector no longer sees any live reference
	 * to it(1).
	 */
	container = (struct container*)
		scm_gc_malloc (sizeof (struct container), "container");

	/* Step 2: Initialize it with straight code.
	 */
	container->array_length= array_length;
	container->array = NULL;
	container->name = SCM_BOOL_F;

	/* Step 3: Create the smob.
	 */
	// SCM_NEWSMOB (smob, container_tag, container);
	smob = scm_new_smob (container_tag, (scm_t_bits)container);

	fprintf (stderr, "[make_container] ptr=0x%x (0x%x,0x%x)\n",
			 (int)smob, (int)((void**)smob)[0], (int)((void**)smob)[1]);

	/* Step 4: Finish the initialization.
	 */
	container->name = name;
	container->array = scm_gc_malloc (array_length, "container array");

	return smob;
}

//__________________________________________________________________________________________________
//$. mark_container ()
/* This function is responsible for marking all SCM objects included
 * in the smob. */
static SCM
mark_container (SCM container_smob)
{
	fprintf (stderr, "[mark_container] ptr=0x%x (0x%x,0x%x)\n",
			 (int)container_smob,
			 (int)((void**)container_smob)[0], (int)((void**)container_smob)[1]);
	/* we simply return container_smob and the caller will mark it. */
	return SCM_CELL_OBJECT_1 (container_smob);
}

//__________________________________________________________________________________________________
//$. free_container ()
static size_t
free_container (SCM container_smob)
{
	fprintf (stderr, "[free_container] ptr=%#x (%#06x,%#x)\n",
			 (int)container_smob,
			 (int)((void**)container_smob)[0], (int)((void**)container_smob)[1]);
	if (SCM_TYP7(container_smob) != (0xff & container_tag)) {
		// bad type, not dbi smob, do not free it
		fprintf (stderr, "[free] error: bad smob 0x%x\n", (int)SCM_TYP16(container_smob));
		return 0;
	}
	return 0;
}

//__________________________________________________________________________________________________
//$. print_container ()
static int
print_container (SCM container_smob, SCM port, scm_print_state* pstate)
{
	struct container* container = (struct container*) SCM_SMOB_DATA (container_smob);
	scm_puts ("#<container ", port);
	scm_display (container->name, port);
	printf (" child=%#x", (int)container->child); fflush(stdout);
	scm_puts (">", port);
	/* non-zero means success */
	return 1;
}

//__________________________________________________________________________________________________
//$. container_set_child ()
static SCM
container_set_child (SCM c, SCM value)
#define FUNC_NAME "container-set-child"
{
	//SCM_VALIDATE_SMOB (1, c, container);
	SCM_ASSERT (SCM_SMOB_PREDICATE (container_tag, c), c, 1, FUNC_NAME);

	/* Set the child of the container to the given value.  */
	struct container* container = (struct container*) SCM_SMOB_DATA (c);
	container-> child = value;
	
	return SCM_UNSPECIFIED;
}
#undef FUNC_NAME


//__________________________________________________________________________________________________
//$. init_container_type()
void
init_container_type (void)
{
	container_tag = scm_make_smob_type ("container", sizeof (struct container));
	fprintf (stderr, "[init] container_tag = 0x%x\n", (int)container_tag);
	scm_set_smob_mark (container_tag, mark_container);
	scm_set_smob_free (container_tag, free_container);
	scm_set_smob_print (container_tag, print_container);
	scm_c_define_gsubr ("make-container", 2, 0, 0, make_container);
	scm_c_define_gsubr ("container-set-child", 2, 0, 0, container_set_child);
}

#if !defined (_CONTAINER_H_)
#define _CONTAINER_H_

void init_container_type (void);

#endif

#include <stdlib.h>
#include <libguile.h>
#include <child.h>
#include <container.h>


//__________________________________________________________________________________________________
//$. inner_main ()
/* This is the function which gets called by scm_boot_guile after the
 * Guile library is completely initialized.*/
static void
inner_main (void *closure, int argc, char **argv)
{
  /* First, we create our data type... */
  init_child_type ();
  init_container_type ();
  /* ... then we start a shell, in which the box data type can be
   * used. */
  scm_shell (argc, argv);
}

//__________________________________________________________________________________________________
//$. main ()
int
main (int argc, char **argv)
{
	/* Initialize Guile, then call `inner_main' with the arguments 0,
	 * argc and argv.  */
	scm_boot_guile (argc, argv, inner_main, 0);
	return 0; /* Never reached.  */
}

objects = main.o container.o child.o

guile_config = /usr/bin/guile-config
GUILE_COMP = $(shell $(guile_config) compile)
GUILE_LINK = $(shell $(guile_config) link)
CFLAGS  = -I. -ggdb -fpic -Wall $(GUILE_COMP) -Wno-pointer-to-int-cast 
-Wno-int-conversion

.PHONY: 
all: test
        GUILE_WARN_DEPRECATED=detailed ./test.scm

test: $(objects)
        gcc $(objects) $(GUILE_LINK) -o $@

%.o: %.c
        gcc $(CFLAGS) $(INCLUDE) -c -MD -o $@ $<

%.i: %.c
        gcc $(CFLAGS) $(INCLUDE) -E -C -dD -dI $< > $@

.PHONY: dump
dump: 
        @echo GUILE_COMP=$(GUILE_COMP)
        @echo GUILE_LINK=$(GUILE_LINK)
        @echo CFLAGS=$(CFLAGS)

.PHONY: clean
clean:
        rm -fr test *~ *.o *.la *.lo .libs *.so *.d *.i

-include $(objects:.o=.d)

# Local Variables:
# tab-width: 4
# mode: makefile-gmake
# End:
#!/bin/sh
# -*- scheme -*-
guile_config=/usr/bin/guile-config
LD_LIBRARY_PATH=$(${guile_config} info libdir)
export LD_LIBRARY_PATH
GUILE_AUTO_COMPILE=0
export GUILE_AUTO_COMPILE
exec "./test" -s $0 "$@"
!#

(format #t "version = ~a\n" (version))
(display "(\n[let begin] ----------------------------------------\n")
(let ((c1 (make-container "my.container.1" 2048))
	  (c2 (make-container "my.container.2" 2048))
	  (ch1 (make-child))
	  (ch2 (make-child))
	  )
  (format #t "ch1 = ~s\n" ch1)
  (format #t "ch2 = ~s\n" ch2)
  (container-set-child c1 ch1)
  (container-set-child c2 ch2)
  (format #t "c1 = ~s\n" c1)
  (format #t "c2 = ~s\n" c2)
  (gc)
  )
(display "[let end] ------------------------------------------\n)\n")
(display "\n+----------------------------------------------------+\n")
(display "|  What are the following mark functions called for? |\n")
(display "+----------------------------------------------------+\n")
(gc)

;; Local Variables:
;; tab-width: 4
;; End:

Reply via email to