initial
[prop.git] / lib-src / gc / gc.cc
blob04ea53af320b8badbade8596f297143fd95d1b44
1 //////////////////////////////////////////////////////////////////////////////
2 // NOTICE:
3 //
4 // ADLib, Prop and their related set of tools and documentation are in the
5 // public domain. The author(s) of this software reserve no copyrights on
6 // the source code and any code generated using the tools. You are encouraged
7 // to use ADLib and Prop to develop software, in both academic and commercial
8 // settings, and are welcomed to incorporate any part of ADLib and Prop into
9 // your programs.
11 // Although you are under no obligation to do so, we strongly recommend that
12 // you give away all software developed using our tools.
14 // We also ask that credit be given to us when ADLib and/or Prop are used in
15 // your programs, and that this notice be preserved intact in all the source
16 // code.
18 // This software is still under development and we welcome(read crave for)
19 // any suggestions and help from the users.
21 // Allen Leung (leunga@cs.nyu.edu)
22 // 1994
23 //////////////////////////////////////////////////////////////////////////////
25 #include <iostream.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <AD/gc/gcconfig.h> // system configuration
31 #include <AD/gc/gc.h> // garbage collector base class
32 #include <AD/gc/gcobject.h> // garbage collectable objects
33 #include <AD/gc/gctimer.h> // timer stuff
34 #include <AD/gc/gcmacros.h> // useful macros
36 //////////////////////////////////////////////////////////////////////////////
37 // Static data
38 //////////////////////////////////////////////////////////////////////////////
39 GC * GC::collectors[ GC_MAX_NUMBER_OF_COLLECTORS ];
40 int GC::number_of_collectors = 0;
42 //////////////////////////////////////////////////////////////////////////////
43 // Method that returns a name for the collector
44 //////////////////////////////////////////////////////////////////////////////
45 const char * GC::my_name() const { return "GC"; }
47 //////////////////////////////////////////////////////////////////////////////
48 // Constructor
49 //////////////////////////////////////////////////////////////////////////////
50 GC:: GC()
51 : Mem("GC"),
52 verbosity_level( GC::gc_notify_minor_collection |
53 GC::gc_notify_major_collection |
54 GC::gc_notify_weak_pointer_collection |
55 GC::gc_notify_heap_expansion |
56 GC::gc_notify_heap_info |
57 GC::gc_print_collection_time
58 ),
59 gc_ratio(75),
60 console(&cerr),
61 should_finalize(false),
62 should_collect_weak_pointers(true)
65 // Assign a gc ID number to each collector.
66 // It must be non-zero.
68 if (number_of_collectors >= GC_MAX_NUMBER_OF_COLLECTORS) {
69 error ("Number of collectors exceeded the hard limit");
70 exit(1);
72 for (id = 1; id < GC_MAX_NUMBER_OF_COLLECTORS; id++) {
73 if (collectors[id] == 0) { collectors[id] = this; break; }
75 number_of_collectors++;
78 //////////////////////////////////////////////////////////////////////////////
79 // Destructor
80 //////////////////////////////////////////////////////////////////////////////
81 GC::~GC()
82 { collectors[id] = 0;
83 number_of_collectors--;
86 //////////////////////////////////////////////////////////////////////////////
87 // The default method for free doesn't do anything.
88 //////////////////////////////////////////////////////////////////////////////
89 void GC::free(void * /* obj */) {}
91 //////////////////////////////////////////////////////////////////////////////
92 // The default method for c_alloc just calls the m_alloc routine.
93 // We assume all subclasses already initialize memory to zeros.
94 //////////////////////////////////////////////////////////////////////////////
95 void * GC::c_alloc(size_t n) { return m_alloc(n); }
96 void * GC::m_alloc(size_t) { error("m_alloc() is unimplemented"); return 0; }
98 //////////////////////////////////////////////////////////////////////////////
99 // Methods that deal the verbosity and console messages.
100 //////////////////////////////////////////////////////////////////////////////
101 int GC::verbosity() const { return verbosity_level; }
102 Bool GC::is_verbose() const
103 { return verbosity_level &
104 (gc_notify_minor_collection | gc_notify_major_collection);
106 Bool GC::is_debugging() const
107 { return verbosity_level & gc_print_debugging_info; }
108 void GC::set_verbosity (int v) { verbosity_level = v; }
110 void GC::set_console (ostream& f) { console = &f; }
111 void GC::set_console (ostream * f) { set_console (*f); }
112 ostream& GC::get_console () const { return *console; }
113 Bool GC::has_console () const { return console != 0; }
115 //////////////////////////////////////////////////////////////////////////////
116 // Default set gc ratio method does nothing
117 //////////////////////////////////////////////////////////////////////////////
118 void GC::set_gc_ratio(int r) { gc_ratio = r; }
119 void GC::set_initial_heap_size(size_t) {}
120 void GC::set_min_heap_growth (size_t) {}
122 //////////////////////////////////////////////////////////////////////////////
123 // Method to set/reset the finalization flag
124 //////////////////////////////////////////////////////////////////////////////
125 Bool GC::set_finalization(Bool f)
126 { Bool old_flag = should_finalize;
127 should_finalize = f;
128 return old_flag;
131 //////////////////////////////////////////////////////////////////////////////
132 // Method to set/reset the weak pointer collection flag
133 //////////////////////////////////////////////////////////////////////////////
134 Bool GC::set_weak_pointer_collection(Bool f)
135 { Bool old_flag = should_collect_weak_pointers;
136 should_collect_weak_pointers = f;
137 return old_flag;
140 //////////////////////////////////////////////////////////////////////////////
141 // Method for printing an error message
142 //////////////////////////////////////////////////////////////////////////////
143 void GC::error (const char * message) const
144 { ostream * f;
145 if (has_console()) f = &get_console(); else f = &cerr;
146 (*f) << '[' << my_name() << ": " << message << "]\n" << flush;
149 //////////////////////////////////////////////////////////////////////////////
150 // Method to reset statistics
151 //////////////////////////////////////////////////////////////////////////////
152 void GC::reset_statistics(GC::Statistics& stat)
153 { stat.bytes_used = 0;
154 stat.bytes_managed = 0;
155 stat.bytes_free = 0;
156 stat.number_of_collections = 0;
157 stat.number_of_heap_expansions = 0;
158 stat.gc_user_time.clear();
159 stat.gc_system_time.clear();
160 stat.total_gc_user_time.clear();
161 stat.total_gc_system_time.clear();
164 //////////////////////////////////////////////////////////////////////////////
165 // Method to print the statistics
166 //////////////////////////////////////////////////////////////////////////////
167 ostream& GC::print_statistics(ostream& f)
168 { Statistics s = statistics();
169 f << "[ Algorithm: " << s.algorithm << '\n'
170 << " Version: " << s.version << '\n'
171 << " Bytes used: " << s.bytes_used << '\n'
172 << " Bytes in heap: " << s.bytes_managed << '\n'
173 << " Bytes available: " << s.bytes_free << '\n'
174 << " Number of collections: " << s.number_of_collections << '\n'
175 << " Number of heap expansions: " << s.number_of_heap_expansions << '\n'
176 #ifdef GC_USE_TIMER
177 << " Total GC time: "
178 << (s.total_gc_system_time + s.total_gc_user_time)
179 << " (user: " << s.total_gc_user_time
180 << ", system: " << s.total_gc_system_time << ")\n"
181 #endif
182 << "]\n"
184 return f;
187 //////////////////////////////////////////////////////////////////////////////
188 // Method for scanning user roots
189 //////////////////////////////////////////////////////////////////////////////
190 void GC::scan_user_roots()
191 { int i;
193 // scan root objects.
194 for (i = 0; i < number_of_objects(); i++) {
195 root_obj(i).trace(this);
198 // scan root pointers
199 for (i = 0; i < number_of_pointers(); i++) {
200 GCObject * ptr = root_ptr(i);
201 if (ptr) ptr->trace(this);