• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdesdk API Reference
  • KDE Home
  • Contact Us
 

kcachegrind

  • sources
  • kde-4.14
  • kdesdk
  • kcachegrind
  • libcore
pool.cpp
Go to the documentation of this file.
1 /* This file is part of KCachegrind.
2  Copyright (C) 2002-2004 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
3 
4  KCachegrind is free software; you can redistribute it and/or
5  modify it under the terms of the GNU General Public
6  License as published by the Free Software Foundation, version 2.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; see the file COPYING. If not, write to
15  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  Boston, MA 02110-1301, USA.
17 */
18 
19 #include <string.h>
20 #include <stdlib.h>
21 #include <qglobal.h>
22 #include "pool.h"
23 
24 // FixPool
25 
26 #define CHUNK_SIZE 100000
27 
28 struct SpaceChunk
29 {
30  struct SpaceChunk* next;
31  unsigned int used;
32  char space[1];
33 };
34 
35 FixPool::FixPool()
36 {
37  _first = _last = 0;
38  _reservation = 0;
39  _count = 0;
40  _size = 0;
41 }
42 
43 FixPool::~FixPool()
44 {
45  struct SpaceChunk* chunk = _first, *next;
46 
47  while(chunk) {
48  next = chunk->next;
49  free(chunk);
50  chunk = next;
51  }
52 
53  if (0) qDebug("~FixPool: Had %d objects with total size %d\n",
54  _count, _size);
55 }
56 
57 void* FixPool::allocate(unsigned int size)
58 {
59  if (!ensureSpace(size)) return 0;
60 
61  _reservation = 0;
62  void* result = _last->space + _last->used;
63  _last->used += size;
64 
65  _count++;
66  _size += size;
67 
68  return result;
69 }
70 
71 void* FixPool::reserve(unsigned int size)
72 {
73  if (!ensureSpace(size)) return 0;
74  _reservation = size;
75 
76  return _last->space + _last->used;
77 }
78 
79 
80 bool FixPool::allocateReserved(unsigned int size)
81 {
82  if (_reservation < size) return false;
83 
84  _reservation = 0;
85  _last->used += size;
86 
87  _count++;
88  _size += size;
89 
90  return true;
91 }
92 
93 bool FixPool::ensureSpace(unsigned int size)
94 {
95  if (_last && _last->used + size <= CHUNK_SIZE) return true;
96 
97  struct SpaceChunk* newChunk;
98 
99  // we do not allow allocation sizes > CHUNK_SIZE
100  if (size > CHUNK_SIZE) return false;
101 
102  newChunk = (struct SpaceChunk*) malloc(sizeof(struct SpaceChunk) +
103  CHUNK_SIZE);
104  if (!newChunk) {
105  qFatal("ERROR: Out of memory. Sorry. KCachegrind has to terminate.\n\n"
106  "You probably tried to load a profile data file too huge for"
107  "this system. You could try loading this file on a 64-bit OS.");
108  exit(1);
109  }
110  newChunk->next = 0;
111  newChunk->used = 0;
112 
113  if (!_last) {
114  _last = _first = newChunk;
115  }
116  else {
117  _last->next = newChunk;
118  _last = newChunk;
119  }
120  return true;
121 }
122 
123 
124 // DynPool
125 
126 DynPool::DynPool()
127 {
128  _data = (char*) malloc(CHUNK_SIZE);
129  _used = 0;
130  _size = CHUNK_SIZE;
131 
132  // end marker
133  *(int*)_data = 0;
134 }
135 
136 DynPool::~DynPool()
137 {
138  // we could check for correctness by iteration over all objects
139 
140  ::free(_data);
141 }
142 
143 bool DynPool::allocate(char** ptr, unsigned int size)
144 {
145  // round up to multiple of 4
146  size = (size+3) & ~3;
147 
148  /* need 12 bytes more:
149  * - 4 bytes for forward chain
150  * - 4 bytes for pointer to ptr
151  * - 4 bytes as end marker (not used for new object)
152  */
153  if (!ensureSpace(size + 12)) return false;
154 
155  char** obj = (char**) (_data+_used);
156  obj[0] = (char*)(_data + _used + size + 8);
157  obj[1] = (char*)ptr;
158  *(int*)(_data+_used+size+8) = 0;
159  *ptr = _data+_used+8;
160 
161  _used += size + 8;
162 
163  return true;
164 }
165 
166 void DynPool::free(char** ptr)
167 {
168  if (!ptr ||
169  !*ptr ||
170  (*(char**)(*ptr - 4)) != (char*)ptr )
171  qFatal("Chaining error in DynPool::free");
172 
173  (*(char**)(*ptr - 4)) = 0;
174  *ptr = 0;
175 }
176 
177 bool DynPool::ensureSpace(unsigned int size)
178 {
179  if (_used + size <= _size) return true;
180 
181  unsigned int newsize = _size *3/2 + CHUNK_SIZE;
182  char* newdata = (char*) malloc(newsize);
183 
184  unsigned int freed = 0, len;
185  char **p, **pnext, **pnew;
186 
187  qDebug("DynPool::ensureSpace size: %d => %d, used %d. %p => %p",
188  _size, newsize, _used, _data, newdata);
189 
190  pnew = (char**) newdata;
191  p = (char**) _data;
192  while(*p) {
193  pnext = (char**) *p;
194  len = (char*)pnext - (char*)p;
195 
196  if (0) qDebug(" [%8p] Len %d (ptr %p), freed %d (=> %p)",
197  p, len, p[1], freed, pnew);
198 
199  /* skip freed space ? */
200  if (p[1] == 0) {
201  freed += len;
202  p = pnext;
203  continue;
204  }
205 
206  // new and old still at same address ?
207  if (pnew == p) {
208  pnew = p = pnext;
209  continue;
210  }
211 
212  // copy object
213  pnew[0] = (char*)pnew + len;
214  pnew[1] = p[1];
215  memcpy((char*)pnew + 8, (char*)p + 8, len-8);
216 
217  // update pointer to object
218  char** ptr = (char**) p[1];
219  if (*ptr != ((char*)p)+8)
220  qFatal("Chaining error in DynPool::ensureSpace");
221  *ptr = ((char*)pnew)+8;
222 
223  pnew = (char**) pnew[0];
224  p = pnext;
225  }
226  pnew[0] = 0;
227 
228  unsigned int newused = (char*)pnew - (char*)newdata;
229  qDebug("DynPool::ensureSpace size: %d => %d, used %d => %d (%d freed)",
230  _size, newsize, _used, newused, freed);
231 
232  ::free(_data);
233  _data = newdata;
234  _size = newsize;
235  _used = newused;
236 
237  return true;
238 }
239 
240 /* Testing the DynPool
241 int main()
242 {
243  char* bufs[CHUNK_SIZE];
244  int i;
245 
246  DynPool p;
247 
248  for(i=0;i<CHUNK_SIZE;i++) {
249  p.allocate(bufs+i, 10+i%10);
250  if (((i%3)==0) && (i>20))
251  p.free(bufs+i-20);
252  }
253 
254  for(i=0;i<CHUNK_SIZE;i++) {
255  if ((bufs[i]==0) || ((i%7)==0)) continue;
256  p.free(bufs+i);
257  }
258 
259  for(i=0;i<CHUNK_SIZE;i++) {
260  if (bufs[i]) continue;
261  p.allocate(bufs+i, 10+i%10);
262  }
263 }
264 */
pool.h
FixPool::allocateReserved
bool allocateReserved(unsigned int size)
Before calling this, you have to reserve at least bytes with reserveSpace().
Definition: pool.cpp:80
FixPool::reserve
void * reserve(unsigned int size)
Reserve space.
Definition: pool.cpp:71
DynPool::allocate
bool allocate(char **ptr, unsigned int size)
Take bytes from the pool, changing <*ptr> to point to this allocated space.
Definition: pool.cpp:143
DynPool::free
void free(char **ptr)
To resize, first allocate new space, and free old afterwards.
Definition: pool.cpp:166
CHUNK_SIZE
#define CHUNK_SIZE
Definition: pool.cpp:26
DynPool::DynPool
DynPool()
Definition: pool.cpp:126
FixPool::FixPool
FixPool()
Definition: pool.cpp:35
FixPool::allocate
void * allocate(unsigned int size)
Take bytes from the pool.
Definition: pool.cpp:57
DynPool::~DynPool
~DynPool()
Definition: pool.cpp:136
FixPool::~FixPool
~FixPool()
Definition: pool.cpp:43
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:39:50 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kcachegrind

Skip menu "kcachegrind"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdesdk API Reference

Skip menu "kdesdk API Reference"
  • kapptemplate
  • kcachegrind
  • kompare
  • lokalize
  • umbrello
  •   umbrello

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal