A simple C garbage collector

Source: Internet
Author: User
Tags data structures extend garbage collection

This time to try to achieve a simple C-language garbage collector, the code is not much, but for my experience, it really cost a lot of thought.
Thank you for Yunfeng's open Source: Cloud Wind: blog.codingnow.com/2008/06/gc_for_c.html
and LOGOS. A conceptual version of YFGC's interpretation and implementation: Logos:www.cppblog.com/darkdestiny
I know there are a lot of things to think about in my own realization. But still decided to stick it out, tell me the idea of realization, there are deficiencies in the local people point out to correct.
We know that garbage collection technology is mainly divided into the following, they have their own advantages and disadvantages:
1. Citation technology (Reference counting)
2. Mark Clear (Mark-sweep)
3. Mark Finishing/tightening (mark-compact)
4. Node replication (Copying)
5. Collection of generational (generational collecting)
I'm not going to go into a variety of ideas here, Google has. My requirement is: Require garbage collection can naturally solve the problem of circular reference, occupy not too much space, lightweight implementation, solve the problem of memory fragmentation.
Here I am using the tag cleanup algorithm, memory allocation uses the memory pool.
The first is to give the interface of the memory pool, implementation in my previous article has said, do not post it out. The implementation of the memory pool draws on the SGI STL's implementation approach.    Code: #ifndef _mem_pool_h #define _MEM_POOL_H #include <stddef.h> void *mem_malloc (size_t n);    void Mem_free (void *p, size_t n);       void *mem_realloc (void* ptr, size_t NEW_SZ, size_t OLD_SZ); #endif

     then look at the GC interface: Code: #ifndef  garbage_collector_h    #define  garbage_ Collector_h       #include  <stddef.h>       #define  my_ Malloc mem_malloc    #define  my_free mem_free    #define  my_realloc  Mem_realloc      /* define the level of node */   # Define node_root_level 0 /* the node is global Variable or in  main ()  */   #define  node_now_level 1  /* the node is  just use in  present fucntion */   #define  node_pre_level  2  /* the node is be referenced by call function  */         void gc_init ();    Void gc_exit ();      Void func_end (void *p, ..);    Void gc_link (Void *p, int level);      /* gc will mark the memory in gc_enter/gc_leave  for collect later */   Void gc_enter ();    Void gc_leave ();       void gc_collect ();       Void *gc_malloc (size_t sz, void  (*finalizer) (void *));    Void *gc_realloc (VOID&NBSP;*P,&NBSP;SIZE_T&NBSP;SZ);       #endif   

   data structures used: code:struct node {       int mark;           /* mark for gc collect */       int level;         /* the  node leavel */       struct {            void *mem;     /* the pointer point  to memory*/           int size;       /* the size of memrory */            void  (*finalizer) (void *);  /* destruction when the mem  be free */       }n;   };       static struct {       struct node *pool;   /* an  array for store nodes */       int size;             /* the size of pool */        int free;             /* the next free node in pool */        Struct stack *stack; /* the stack used for store Pointer in fuction  */  } e;  

      The level values here are: Node_root_level, Node_now_level, Node_pre_level. Based on this consideration, we know that allocating a chunk of memory dynamically, if you want to extend its lifetime, is either passed back through the function return value, either through a multilevel pointer, or directly to a global variable. So this GC is based on a strategy where the node level value of the user-allocated memory block is initialized to Node_now_level, and if the user needs to extend its lifetime to the previous function or global variable, call Gc_link and pass in the corresponding level value. It is only necessary to call Func_end at the end of the function, when passing dynamic memory through the return value, only when its lifetime needs to be extended to the upper-level function. The Func_end function is to set the level value of the memory block to Node_now_level.
Knowing the life of the end point, the mark is simple. Gc_leave is responsible for EVEL the nodes in the current function stack as node_now_level to mark_collect, thus recovering them in gc_collect. What you need to say here is that the memory allocated in the main () function and the memory that is attached to the global variable are freed in Gc_exit.
      the general process to know, the following is the implementation: Code: #include  <stdio.h>    #include   <stdlib.h>    #include  <stdarg.h>    #include  <assert.h>     #include   "stack.h"    #include   "mem_pool.h"    #include   "gc.h"              #define  POOL_INITIAL_NUMBER 1024 /* the  Initial number of nodes in pool */   #define  pool_max_number 4096      /* the Max Number of nodes in pool */       #define  STACK_SECTION_TAG NULL /* the tag to section the  stack */      #define  MARK_INITIAL -1     /*  the node initialed */   #define  mark_reserve 0      /* the node marked for reserve */   #define  mark_collect  1      /* the node marked for collect */       struct node {       int mark;           /* mark for gc collect */       int level;         /* the  node leavel */       struct {            void *mem;     /* the pointer point  to memory*/           int size;       /* the size of memrory */            void  (*finalizer) (void *);  /* destruction when the mem be  free */       }n;   };       static struct {       struct node * pool;   /* an array for store the pointer of node  */       int size;             /* the size of pool */       int  Free;            /* the next free  node in pool */       struct stack *stack; /*  the stack used for store Pointer in fuction */  } E;       Static bool pool_Compact ()    {       int i, j;         struct node temp;                for  (i = 0; i  < e.free; i++)  {           if  ( e.pool[i].mark == mark_initial)  {                temp = E.pool[i];             for  (j = e.free; j > i;  j--)  {                    if  (e.pool[j].mark != mark_initial)  {                        e.pool[i ] = e.pool[j];  &nBsp                      E.pool[j] = temp;                         break;                    }                }             }        }                for  (i = 0; i < e.size; i++)  {            if  (e.pool[i].mark == mark_initial)  {               E.free =  I                break;            }        }                return e.free >= e.size ?  true : false;   }       static void node_init ()    {        int i;                for  (i = e.free; i  < e.size; i++)  {           e.pool[i]. mark = mark_initial;            E.pool[i].level = NODE_NOW_LEVEL;            E.pool[i].n.mem = NULL;            e.pool[i].n.finalizer =&nbsp NULL;        }   }       Static void pool_expand () & nbsp;  {       int expand_size;        bool  expand = false;                expand_size = e.size *  2;        if  (expand_size >= pool_max_number * sizeof ( Struct node))  {            expand =  Pool_compact ();        }                  if  (expand)  {           E.pool =  ( struct node *) My_realloc (e.pool, expand_size * sizeof (struct node),         &nBsp;       e.size * sizeof (Struct node));            E.free = E.size;            E.size = expand_size;                         /* init the node */            node_init ();        }      }       static void  node_alloc (void *p, size_t sz, void  (*finalizer) (void *))    {        if  (e.free >= e.size)  {            pool_expand ();        }     E.pool[E.free].mark = MARK_RESERVE;        E.pool[E.free].level = NODE_NOW_LEVEL;        E.pool[E.free].n.mem = p;        e.pool[e.free].n.size = sz; // for mem_free        E.pool[E.free].n.finalizer = finalizer;                    E.free++;         }             static void  Pool_init ()    {       E.pool =  (struct node *) my_ malloc (pool_initial_number * sizeof (Struct node));        E.free = 0;        E.size = POOL_INITIAL_NUMBER;                /* init the node * /     &Nbsp; node_init ();   }             void gc_init ()    {       E.pool = NULL;        E.size = 0;        E.free = -1;        e.stack = init_stack ();                pool_init ();   }       Void gc_link (void *p, int level)    {        int i;                for  (i = 0; i  < e.free; i++)  {           if  ( e.pool[i].n.mem == p)  {                e.pool[i].level = level;                break;            }        }    }       Void gc_enter ()    {       push (e.stack,  stack_section_tag);   }      /* accordind to the level of nodes,  mark nodes. if in present stack section     * of function ,  there are some nodes '  life extend father function ' s life     * which callthe present function, then push these nodes  in stack section    * of father ' s function.    */      void gc_leave ()    {        void *p;        struct stack *stack_temp;                stack_temp = init_stack ();        while  ((P = top (e.stack))  != stack_section_tag)  {           int i;                         /* whether  mark for gc collect or not by searching for the node     &

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.