00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <winstd.H>
00027
00028 #include <utility>
00029
00030 #if defined(BL_OLD_STL)
00031 #include <string.h>
00032 #else
00033 #include <cstring>
00034 #endif
00035
00036 #include <CArena.H>
00037
00038 CArena::CArena (size_t hunk_size)
00039 {
00040
00041
00042
00043 m_hunk = Arena::align(hunk_size == 0 ? DefaultHunkSize : hunk_size);
00044 m_used = 0;
00045
00046 BL_ASSERT(m_hunk >= hunk_size);
00047 BL_ASSERT(m_hunk%sizeof(Arena::Word) == 0);
00048 }
00049
00050 CArena::~CArena ()
00051 {
00052 for (unsigned int i = 0; i < m_alloc.size(); i++)
00053 ::operator delete(m_alloc[i]);
00054 }
00055
00056 void*
00057 CArena::alloc (size_t nbytes)
00058 {
00059 nbytes = Arena::align(nbytes == 0 ? 1 : nbytes);
00060
00061
00062
00063 NL::iterator free_it = m_freelist.begin();
00064
00065 for ( ; free_it != m_freelist.end(); ++free_it)
00066 if ((*free_it).size() >= nbytes)
00067 break;
00068
00069 void* vp = 0;
00070
00071 if (free_it == m_freelist.end())
00072 {
00073 const size_t N = nbytes < m_hunk ? m_hunk : nbytes;
00074
00075 vp = ::operator new(N);
00076
00077 m_used += N;
00078
00079 m_alloc.push_back(vp);
00080
00081 if (nbytes < m_hunk)
00082 {
00083
00084
00085
00086
00087
00088 void* block = static_cast<char*>(vp) + nbytes;
00089
00090 m_freelist.insert(m_freelist.end(), Node(block, m_hunk-nbytes));
00091 }
00092 }
00093 else
00094 {
00095 BL_ASSERT((*free_it).size() >= nbytes);
00096 BL_ASSERT(m_busylist.find(*free_it) == m_busylist.end());
00097
00098 vp = (*free_it).block();
00099
00100 if ((*free_it).size() > nbytes)
00101 {
00102
00103
00104
00105
00106
00107 Node freeblock = *free_it;
00108
00109 freeblock.size(freeblock.size() - nbytes);
00110
00111 freeblock.block(static_cast<char*>(vp) + nbytes);
00112
00113 m_freelist.insert(free_it, freeblock);
00114 }
00115
00116 m_freelist.erase(free_it);
00117 }
00118
00119 m_busylist.insert(Node(vp, nbytes));
00120
00121 BL_ASSERT(!(vp == 0));
00122
00123 return vp;
00124 }
00125
00126 void
00127 CArena::free (void* vp)
00128 {
00129 if (vp == 0)
00130
00131
00132
00133 return;
00134
00135
00136
00137 NL::iterator busy_it = m_busylist.find(Node(vp,0));
00138
00139 BL_ASSERT(!(busy_it == m_busylist.end()));
00140 BL_ASSERT(m_freelist.find(*busy_it) == m_freelist.end());
00141
00142 void* freeblock = static_cast<char*>((*busy_it).block());
00143
00144
00145
00146 std::pair<NL::iterator,bool> pair_it = m_freelist.insert(*busy_it);
00147
00148 BL_ASSERT(pair_it.second == true);
00149
00150 NL::iterator free_it = pair_it.first;
00151
00152 BL_ASSERT(free_it != m_freelist.end() && (*free_it).block() == freeblock);
00153
00154
00155
00156 m_busylist.erase(busy_it);
00157
00158
00159
00160 if (!(free_it == m_freelist.begin()))
00161 {
00162 NL::iterator lo_it = free_it;
00163
00164 --lo_it;
00165
00166 void* addr = static_cast<char*>((*lo_it).block()) + (*lo_it).size();
00167
00168 if (addr == (*free_it).block())
00169 {
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 Node* node = const_cast<Node*>(&(*lo_it));
00182 BL_ASSERT(!(node == 0));
00183 node->size((*lo_it).size() + (*free_it).size());
00184 m_freelist.erase(free_it);
00185 free_it = lo_it;
00186 }
00187 }
00188
00189 NL::iterator hi_it = free_it;
00190
00191 void* addr = static_cast<char*>((*free_it).block()) + (*free_it).size();
00192
00193 if (++hi_it != m_freelist.end() && addr == (*hi_it).block())
00194 {
00195
00196
00197
00198 Node* node = const_cast<Node*>(&(*free_it));
00199 BL_ASSERT(!(node == 0));
00200 node->size((*free_it).size() + (*hi_it).size());
00201 m_freelist.erase(hi_it);
00202 }
00203 }
00204
00205 size_t
00206 CArena::heap_space_used () const
00207 {
00208 return m_used;
00209 }