Edinburgh Speech Tools  2.1-release
EST_Chunk.h
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 #if ! defined(__EST_CHUNK_H__)
44 #define __EST_CHUNK_H__
45 
46 #include <iostream>
47 
48 #include <climits>
49 #include <sys/types.h>
50 
51 // Warn when getting a writable version of a shared chunk --
52 // useful for minimising copies.
53 
54 /* #define __INCLUDE_CHUNK_WARNINGS__ (1) */
55 
56 #if defined(__INCLUDE_CHUNK_WARNINGS__)
57 # define CHUNK_WARN(WHAT) do { cerr << "chunk: " <<WHAT << "\n";} while (0)
58 #else
59 # define CHUNK_WARN(WHAT) // empty
60 #endif
61 
62 #define __CHUNK_INLINE_AGGRESSIVELY__ (1)
63 
64 #if defined(__CHUNK_INLINE_AGGRESSIVELY__)
65 # define CII(BODY) BODY
66 #else
67 # define CII(BODY) /* empty */
68 #endif
69 
70 
71 #include "EST_walloc.h"
72 
73 using std::ostream;
74 
75  /************************************************************************/
76  /* */
77  /* EST_Chunk is a use-counted chunk of memory. You shouldn't be able */
78  /* to do anything to it except create it and manipulate it via */
79  /* EST_ChunkPtr. The private operator::new takes a placement argument */
80  /* which is actually the number of bytes of memory in the body of the */
81  /* chunk. */
82  /* */
83  /* If the use counter overflows, it sticks. Anything with more than */
84  /* SHRT_MAX references to it is probably permanent. */
85  /* */
86  /************************************************************************/
87 
88 class EST_ChunkPtr;
89 
90 class EST_Chunk {
91  public:
92  typedef unsigned short use_counter;
93 # define MAX_CHUNK_COUNT (USHRT_MAX)
94  typedef int EST_chunk_size;
95 # define MAX_CHUNK_SIZE (INT_MAX)
96 
97  private:
98  use_counter count;
99  EST_chunk_size size;
100  int malloc_flag; // set if this was got from malloc (rather than new)
101  char memory[1];
102 
103  EST_Chunk(void);
104  ~EST_Chunk();
105 
106  EST_Chunk *operator & ();
107  void *operator new (size_t size, size_t bytes);
108  void operator delete (void *it);
109 
110  void operator ++ ()
111  CII({if (count < MAX_CHUNK_COUNT) ++count; });
112 
113  void operator -- ()
114  CII({if (count < MAX_CHUNK_COUNT) if (--count == 0) delete this;});
115 
116  public:
117  friend class EST_ChunkPtr;
118 
119  friend EST_ChunkPtr chunk_allocate(size_t bytes);
120  friend EST_ChunkPtr chunk_allocate(size_t bytes, const char *initial, size_t initial_len);
121  friend EST_ChunkPtr chunk_allocate(size_t bytes, const EST_ChunkPtr &initial, size_t initial_start, size_t initial_len);
122 
123  friend void cp_make_updatable(EST_ChunkPtr &shared, EST_chunk_size inuse);
124  friend void cp_make_updatable(EST_ChunkPtr &shared);
125 
126  friend void grow_chunk(EST_ChunkPtr &shared, EST_chunk_size inuse, EST_chunk_size newsize);
127  friend void grow_chunk(EST_ChunkPtr &shared, EST_chunk_size newsize);
128 
129  friend ostream &operator << (ostream &s, const EST_Chunk &chp);
130  friend void tester(void);
131 };
132 
133  /************************************************************************/
134  /* */
135  /* Pointers to chunks. Initialising them and assigning them around */
136  /* keeps track of use counts. We allow them to be cast to char * as a */
137  /* way of letting people work on them with standard functions, */
138  /* however it is bad voodoo to hold on to such a cast chunk for more */
139  /* than a trivial amount of time. */
140  /* */
141  /************************************************************************/
142 
144  private:
145  EST_Chunk *ptr;
146 
147  EST_ChunkPtr(EST_Chunk *chp) CII({
148  if ((ptr=chp))
149  ++ *ptr;
150  });
151  public:
152  EST_ChunkPtr(void) { ptr = (EST_Chunk *)NULL; };
153 
155  ptr=cp.ptr;
156  if (ptr)
157  ++ *ptr;
158  });
159 
160  ~EST_ChunkPtr(void) CII({ if (ptr) -- *ptr; });
161 
162  int size(void) const { return ptr?ptr->size:0; };
163  int shareing(void) const { return ptr?(ptr->count >1):0; };
164  int count(void) const { return ptr?(ptr->count):-1; };
165 
166  EST_ChunkPtr &operator = (EST_ChunkPtr cp) CII({
167  // doing it in this order means self assignment is safe.
168  if (cp.ptr)
169  ++ *(cp.ptr);
170  if (ptr)
171  -- *ptr;
172  ptr=cp.ptr;
173  return *this;
174  });
175 
176  // If they manage to get hold of one...
177  // Actually usually used to assign NULL and so (possibly) deallocate
178  // the chunk currently pointed to.
179  EST_ChunkPtr &operator = (EST_Chunk *chp) CII({
180  // doing it in this order means self assignment is safe.
181  if (chp)
182  ++ *chp;
183  if (ptr)
184  -- *ptr;
185  ptr=chp;
186  return *this;
187  });
188 
189  // Casting to a non-const pointer causes a
190  // warning to stderr if the chunk is shared.
191  operator char*() CII({
192  if (ptr && ptr->count > 1)
193  {
194  CHUNK_WARN("getting writable version of shared chunk\n");
195  cp_make_updatable(*this);
196  }
197  return ptr?&(ptr->memory[0]):(char *)NULL;
198  });
199  operator const char*() const CII({
200  return ptr?&(ptr->memory[0]):(const char *)NULL;
201  });
202  operator const char*() CII({
203  return ptr?&(ptr->memory[0]):(const char *)NULL;
204  });
205 
206 
207  char operator [] (size_t i) const { return ptr->memory[i]; };
208  char &operator () (size_t i) CII({
209  if (ptr->count>1)
210  {
211  CHUNK_WARN("getting writable version of shared chunk\n");
212  cp_make_updatable(*this);
213  }
214  return ptr->memory[i];
215  });
216 
217  // Creating a new one
218  friend EST_ChunkPtr chunk_allocate(size_t size);
219  friend EST_ChunkPtr chunk_allocate(size_t bytes, const char *initial, size_t initial_len);
220  friend EST_ChunkPtr chunk_allocate(size_t bytes, const EST_ChunkPtr &initial, size_t initial_start, size_t initial_len);
221 
222  // Make sure the memory isn`t shared.
223  friend void cp_make_updatable(EST_ChunkPtr &shared, EST_Chunk::EST_chunk_size inuse);
224  friend void cp_make_updatable(EST_ChunkPtr &shared);
225 
226  // Make sure there is enough room (also makes updatable)
227  friend void grow_chunk(EST_ChunkPtr &shared, EST_Chunk::EST_chunk_size inuse, EST_Chunk::EST_chunk_size newsize);
228  friend void grow_chunk(EST_ChunkPtr &shared, EST_Chunk::EST_chunk_size newsize);
229 
230  // we print it by just printing the chunk
231  friend ostream &operator << (ostream &s, const EST_ChunkPtr &cp) { return (s<< *cp.ptr); };
232 
233  friend void tester(void);
234 };
235 
236 EST_ChunkPtr chunk_allocate(size_t bytes);
237 EST_ChunkPtr chunk_allocate(size_t bytes, const char *initial, size_t initial_len);
238 EST_ChunkPtr chunk_allocate(size_t bytes, const EST_ChunkPtr &initial, size_t initial_start, size_t initial_len);
239 
240 
241 #endif
int size(void) const
Definition: EST_Chunk.h:162
#define CII(BODY)
Definition: EST_Chunk.h:65
EST_ChunkPtr(void)
Definition: EST_Chunk.h:152
int count(void) const
Definition: EST_Chunk.h:164
friend void grow_chunk(EST_ChunkPtr &shared, EST_chunk_size inuse, EST_chunk_size newsize)
Definition: EST_Chunk.cc:324
EST_ChunkPtr(const EST_ChunkPtr &cp) CII(
Definition: EST_Chunk.h:154
~EST_ChunkPtr(void) CII(
Definition: EST_Chunk.h:160
unsigned short use_counter
Definition: EST_Chunk.h:92
int EST_chunk_size
Definition: EST_Chunk.h:94
friend void cp_make_updatable(EST_ChunkPtr &shared, EST_chunk_size inuse)
Definition: EST_Chunk.cc:280
int shareing(void) const
Definition: EST_Chunk.h:163
NULL
Definition: EST_WFST.cc:55
#define MAX_CHUNK_COUNT
Definition: EST_Chunk.h:93
friend EST_ChunkPtr chunk_allocate(size_t bytes)
Definition: EST_Chunk.cc:231
friend ostream & operator<<(ostream &s, const EST_Chunk &chp)
Definition: EST_Chunk.cc:336
#define CHUNK_WARN(WHAT)
Definition: EST_Chunk.h:59
friend void tester(void)
friend class EST_ChunkPtr
Definition: EST_Chunk.h:114