Edinburgh Speech Tools  2.1-release
EST_Chunk.cc
Go to the documentation of this file.
1 
2  /************************************************************************/
3  /* */
4  /* Centre for Speech Technology Research */
5  /* University of Edinburgh, UK */
6  /* Copyright (c) 1997 */
7  /* All Rights Reserved. */
8  /* */
9  /* Permission is hereby granted, free of charge, to use and distribute */
10  /* this software and its documentation without restriction, including */
11  /* without limitation the rights to use, copy, modify, merge, publish, */
12  /* distribute, sublicense, and/or sell copies of this work, and to */
13  /* permit persons to whom this work is furnished to do so, subject to */
14  /* the following conditions: */
15  /* 1. The code must retain the above copyright notice, this list of */
16  /* conditions and the following disclaimer. */
17  /* 2. Any modifications must be clearly marked as such. */
18  /* 3. Original authors' names are not deleted. */
19  /* 4. The authors' names are not used to endorse or promote products */
20  /* derived from this software without specific prior written */
21  /* permission. */
22  /* */
23  /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
24  /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
25  /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
26  /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
27  /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
28  /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
29  /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
30  /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
31  /* THIS SOFTWARE. */
32  /* */
33  /************************************************************************/
34  /* */
35  /* Author: Richard Caley (rjc@cstr.ed.ac.uk) */
36  /* Date: February 1997 */
37  /* -------------------------------------------------------------------- */
38  /* */
39  /* Use counted memory chunks and smart pointers to them. */
40  /* */
41  /************************************************************************/
42 
43 #include <cstdlib>
44 #include <iostream>
45 #include <cstring>
46 #include "EST_Chunk.h"
47 
48 using namespace std;
49 
50 EST_Chunk::EST_Chunk ()
51 {
52  count = 0;
53  memory[0] = '\0';
54  // cerr<<"created " << hex << (int)&memory << "," << dec << size <<"\n";
55 }
56 
57 EST_Chunk::~EST_Chunk ()
58 {
59  if (count > 0)
60  {
61  cerr << "deleting chunk with non-zero count\n";
62  exit(1);
63  }
64 
65  // cerr << "deleted "<< hex << (int)&memory << "," << dec << size <<"\n";
66 }
67 
68 // private address-of operator - up to friends to keep use counts correct.
69 
70 EST_Chunk *EST_Chunk::operator & ()
71 {
72  return this;
73 }
74 
75 #if !defined(__CHUNK_INLINE_AGGRESSIVELY__)
76 
77 void EST_Chunk:: operator ++ ()
78 {
79 #if 0
80  if (++count > MAX_CHUNK_COUNT)
81  {
82  cerr<<"max count exceeded\n";
83  exit(1);
84  }
85 #endif
86 
87  if (count < MAX_CHUNK_COUNT)
88  {
89  ++count;
90  }
91 }
92 
93 void EST_Chunk::operator -- ()
94 {
95  if (count-- == 0)
96  {
97  cerr<<"negative count\n";
98  exit(1);
99  }
100  else if (count == 0)
101  {
102  // cerr<<"deleting\n";
103  delete this;
104  }
105 }
106 #endif
107 
108 void *EST_Chunk::operator new (size_t size, size_t bytes)
109 {
110 
111  if (bytes > MAX_CHUNK_SIZE)
112  {
113  cerr<<"trying to make chunk of size "<<bytes<<"\n";
114  }
115 
116 void *it = walloc(char, size+bytes);
117 ((EST_Chunk *)it) -> malloc_flag = 1;
118 
119 
120  // cerr<<"allocated "<<bytes+size<<" byte for chunk\n";
121 
122  ((EST_Chunk *)it) -> size = bytes;
123 
124  return it;
125 }
126 
127 void EST_Chunk::operator delete (void *it)
128 {
129  wfree(it);
130 
131 }
132 
133  /************************************************************************/
134  /* */
135  /* Now the smart pointers. */
136  /* */
137  /************************************************************************/
138 
139 #if !defined(__CHUNK_INLINE_AGGRESSIVELY__)
140 
142 {
143  ptr=chp;
144  if (ptr)
145  ++ *ptr;
146 }
147 
149 {
150  ptr=cp.ptr;
151  if (ptr)
152  ++ *ptr;
153 }
154 
156 {
157  if (ptr)
158  {
159  -- *ptr;
160  }
161 }
162 
164 {
165  // doing it in this order means self assignment is safe.
166  if (cp.ptr)
167  ++ *(cp.ptr);
168  if (ptr)
169  -- *ptr;
170  ptr=cp.ptr;
171  return *this;
172 }
173 
175 {
176  // doing it in this order means self assignment is safe.
177  if (chp)
178  ++ *chp;
179  if (ptr)
180  -- *ptr;
181  ptr=chp;
182  return *this;
183 }
184 
185 EST_ChunkPtr::operator const char*() const
186 {
187  if (ptr)
188  return &(ptr->memory[0]);
189  else
190  return NULL;
191 }
192 
193 EST_ChunkPtr::operator char const*()
194 {
195  return ptr?&(ptr->memory[0]):(const char *)NULL;
196 }
197 
198 EST_ChunkPtr::operator char*()
199 {
200  if (ptr)
201  {
202  if (ptr->count > 1)
203  {
204  CHUNK_WARN("getting writable version of shared chunk");
205  cp_make_updatable(*this);
206  }
207 
208  return &(ptr->memory[0]);
209  }
210  else
211  return NULL;
212 }
213 
214 char &EST_ChunkPtr::operator () (int i) {
215  if (ptr->count>1)
216  {
217  CHUNK_WARN("getting writable version of shared chunk");
218  cp_make_updatable(*this);
219  }
220  return ptr->memory[i];
221  }
222 
223 #endif
224 
225  /************************************************************************/
226  /* */
227  /* Friend function to allocate a chunk in a non count-aware program. */
228  /* */
229  /************************************************************************/
230 
232 {
233  EST_Chunk *cp = new(bytes) EST_Chunk;
234 
235  return (EST_ChunkPtr)cp;
236 }
237 
238 EST_ChunkPtr chunk_allocate(size_t bytes, const char *initial, size_t initial_len)
239 {
240  if (initial_len >= bytes)
241  {
242  cerr<<"initialiser too long\n";
243  abort();
244  }
245 
246  EST_Chunk *cp = new(bytes) EST_Chunk;
247 
248  memcpy(cp->memory, initial, initial_len);
249 
250  cp->memory[initial_len] = '\0';
251 
252  return (EST_ChunkPtr)cp;
253 }
254 
255 EST_ChunkPtr chunk_allocate(size_t bytes, const EST_ChunkPtr &initial, size_t initial_start, size_t initial_len)
256 {
257  if (initial_len >= bytes)
258  {
259  cerr<<"initialiser too long\n";
260  abort();
261  }
262 
263  EST_Chunk *cp = new(bytes) EST_Chunk;
264 
265  memcpy(cp->memory, initial.ptr->memory + initial_start, initial_len);
266 
267  cp->memory[initial_len] = '\0';
268 
269  return (EST_ChunkPtr)cp;
270 }
271 
272  /************************************************************************/
273  /* */
274  /* And one which ensures that a chunk is not shared. Do this before */
275  /* writing to the memory. The first version is told how much of the */
276  /* memory to copy, the second just copies it all. */
277  /* */
278  /************************************************************************/
279 
281 {
282  if (cp.ptr && cp.ptr->count > 1)
283  {
284  EST_Chunk *newchunk = new(cp.ptr->size) EST_Chunk;
285 
286  memcpy(newchunk->memory, cp.ptr->memory, inuse);
287 
288  cp = newchunk;
289  }
290 }
291 
293 {
294  if (cp.ptr && cp.ptr->count > 1)
295  {
296  EST_Chunk *newchunk = new(cp.ptr->size) EST_Chunk;
297 
298  memcpy(newchunk->memory, cp.ptr->memory, cp.ptr->size);
299 
300  cp = newchunk;
301  }
302 }
303 
304  /************************************************************************/
305  /* */
306  /* Make more room in a chunk. If the chunk is already big enough and */
307  /* is unshared then nothing is done. */
308  /* */
309  /************************************************************************/
310 
312 {
313  if (!cp.ptr || cp.ptr->size < newsize)
314  {
315  EST_Chunk *newchunk = new(newsize) EST_Chunk;
316  if (cp.ptr) {
317  cp_make_updatable(cp);
318  memcpy(newchunk->memory, cp.ptr->memory, cp.ptr->size);
319  }
320  cp = newchunk;
321  }
322 }
323 
325 {
326  if (!cp.ptr || cp.ptr->size < newsize)
327  {
328  cp_make_updatable(cp, inuse);
329  EST_Chunk *newchunk = new(newsize) EST_Chunk;
330  if (cp.ptr)
331  memcpy(newchunk->memory, cp.ptr->memory, inuse);
332  cp = newchunk;
333  }
334 }
335 
336 ostream &operator << (ostream &s, const EST_Chunk &ch)
337 {
338  char buff[21];
339 
340  if (ch.size<20)
341  {
342  memcpy(buff, ch.memory, ch.size);
343  buff[ch.size]='\0';
344  }
345  else
346  {
347  memcpy(buff, ch.memory, 20);
348  buff[20]='\0';
349  }
350 
351  return (s<< "[" << ch.size << "!" << ch.count << "!" << buff << "]");
352 }
353 
354 
#define walloc(TYPE, SIZE)
Definition: EST_walloc.h:52
void grow_chunk(EST_ChunkPtr &cp, EST_Chunk::EST_chunk_size newsize)
Definition: EST_Chunk.cc:311
EST_ChunkPtr(void)
Definition: EST_Chunk.h:152
~EST_ChunkPtr(void) CII(
Definition: EST_Chunk.h:160
ostream & operator<<(ostream &s, const EST_Chunk &ch)
Definition: EST_Chunk.cc:336
char & operator()(size_t i) CII(
Definition: EST_Chunk.h:208
int EST_chunk_size
Definition: EST_Chunk.h:94
EST_ChunkPtr & operator=(EST_ChunkPtr cp) CII(
Definition: EST_Chunk.h:166
NULL
Definition: EST_WFST.cc:55
#define MAX_CHUNK_COUNT
Definition: EST_Chunk.h:93
void cp_make_updatable(EST_ChunkPtr &cp, EST_Chunk::EST_chunk_size inuse)
Definition: EST_Chunk.cc:280
EST_ChunkPtr chunk_allocate(size_t bytes)
Definition: EST_Chunk.cc:231
unsigned int size
Definition: EST_TBuffer.h:60
#define CHUNK_WARN(WHAT)
Definition: EST_Chunk.h:59
void wfree(void *p)
Definition: walloc.c:131
#define MAX_CHUNK_SIZE
Definition: EST_Chunk.h:95