00001 /* 00002 The lestes compiler suite 00003 Copyright (C) 2002, 2003, 2004, 2005 Miroslav Tichy 00004 Copyright (C) 2002, 2003, 2004, 2005 Petr Zika 00005 Copyright (C) 2002, 2003, 2004, 2005 Vojtech Hala 00006 Copyright (C) 2002, 2003, 2004, 2005 Jiri Kosina 00007 Copyright (C) 2002, 2003, 2004, 2005 Pavel Sanda 00008 Copyright (C) 2002, 2003, 2004, 2005 Jan Zouhar 00009 Copyright (C) 2002, 2003, 2004, 2005 Rudolf Thomas 00010 00011 This program is free software; you can redistribute it and/or modify 00012 it under the terms of the GNU General Public License as published by 00013 the Free Software Foundation; version 2 of the License. 00014 00015 This program is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 GNU General Public License for more details. 00019 00020 See the full text of the GNU General Public License version 2, and 00021 the limitations in the file doc/LICENSE. 00022 00023 By accepting the license the licensee waives any and all claims 00024 against the copyright holder(s) related in whole or in part to the 00025 work, its use, and/or the inability to use it. 00026 00027 */ 00028 /*! \file 00029 \brief Garbage collector. 00030 00031 Definition of gc class representing garbage collector. 00032 \author pt 00033 */ 00034 #include <lestes/common.hh> 00035 #include <lestes/std/mem/gc.hh> 00036 #include <lestes/std/mem/keystone.hh> 00037 #include <lestes/std/mem/root_pointer.hh> 00038 00039 package(lestes); 00040 package(std); 00041 package(mem); 00042 00043 using namespace ::std; 00044 00045 /*! 00046 Constructor of first existing object initializes gc class. 00047 */ 00048 init_gc::init_gc(void) 00049 { 00050 gc::init(); 00051 } 00052 00053 /*! 00054 Destructor of last existing object runs cleanup of gc class. 00055 */ 00056 init_gc::~init_gc(void) 00057 { 00058 gc::cleanup(); 00059 } 00060 00061 /*! 00062 Counter to keep track of number of initializaton objects. 00063 Reaches zero only after all initialization objects are destroyed. 00064 */ 00065 ulint gc::initialized = 0; 00066 00067 /*! 00068 Initializes static fields of gc class. 00069 Prevents multiple initialization. 00070 */ 00071 void gc::init(void) 00072 { 00073 if (initialized++) return; 00074 // create head of linked list 00075 roots = new root_pointer(false); 00076 keystones = NULL; 00077 marked = NULL; 00078 } 00079 00080 /*! 00081 Performs cleanup of static fields of gc class. 00082 00083 TMA: also cleans all remaining objects. 00084 */ 00085 void gc::cleanup(void) 00086 { 00087 if (--initialized) return; 00088 run(); 00089 delete roots; 00090 } 00091 00092 /*! 00093 Start of doubly linked list of all root pointers. 00094 Initialized to point to the fake head entry. 00095 */ 00096 root_pointer *gc::roots; 00097 00098 /*! 00099 Start of singly linked list of all keystones. 00100 Initially the list is empty. 00101 */ 00102 keystone *gc::keystones; 00103 00104 /*! 00105 Start of singly linked list of marked keystones. 00106 Initially the list is empty. 00107 */ 00108 keystone *gc::marked; 00109 00110 /*! 00111 Counts live root pointers. 00112 \return The number of live root pointers. 00113 */ 00114 ulint gc::live_roots(void) 00115 { 00116 ulint cnt = 0; 00117 for (root_pointer *p = roots->next; p != roots; p = p->next) { 00118 cnt++; 00119 } 00120 return cnt; 00121 } 00122 00123 /*! 00124 Counts live keysones. 00125 \return The number of live keystones. 00126 */ 00127 ulint gc::live_keystones(void) 00128 { 00129 ulint cnt = 0; 00130 for (keystone *p = keystones; p != NULL; p = p->keystones_next) { 00131 cnt++; 00132 } 00133 return cnt; 00134 } 00135 00136 /*! 00137 Runs garbage collection, invoked in new_handler. 00138 Should be invoked explicitly after completing task. 00139 */ 00140 void gc::run(void) 00141 { 00142 // initialize the global marked list 00143 marked = NULL; 00144 // walk through all root pointers and 00145 // insert keystones into marked list 00146 for (root_pointer *p = roots->next; p != roots; p = p->next) { 00147 keystone *key = p->pointer_get(); 00148 if (key) key->enqueue(); 00149 } 00150 00151 // mark all levels of keystones 00152 while (marked != NULL) { 00153 keystone *old = marked; 00154 // initialize the global list for new marking 00155 marked = NULL; 00156 while (old) { 00157 // mark directly reachable keystones 00158 old->gc_mark(); 00159 old = old->marked_next; 00160 } 00161 } 00162 00163 keystone *key = keystones; 00164 00165 // initialize the linked list before new connecting 00166 keystones = NULL; 00167 00168 // walk through all keystones and sweep unmarked 00169 while (key != NULL) { 00170 // save the pointer to next 00171 keystone *tmp = key->keystones_next; 00172 // after sweep_object, obj may be invalid 00173 key->sweep(); 00174 // restore pointer to next 00175 key = tmp; 00176 } 00177 } 00178 00179 end_package(mem); 00180 end_package(std); 00181 end_package(lestes); 00182 /* vim: set ft=lestes : */
1.5.1-20070107