HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SYS_Memory.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: SYS_Memory.h ( SYS Library, C++)
7  *
8  * COMMENTS: Memory tracking utilities
9  */
10 
11 #ifndef __SYS_Memory__
12 #define __SYS_Memory__
13 
14 #include "SYS_API.h"
15 #include "SYS_Align.h"
16 #include "SYS_AtomicInt.h"
17 #include "SYS_Types.h"
18 
19 #include <cstddef>
20 
21 /// Memory Tracking
22 ///
23 /// This class provides a mechanism for tracking memory usage. If all
24 /// memory allocation and freeing is registered with this class, then
25 /// the memory footprint and resource usage can be tracked.
26 ///
27 /// There is a companion class at UT which allows for printing of the memory
28 /// statistics.
29 ///
30 /// An example of how to use this might be:
31 ///
32 /// enum {
33 /// MEM_DEBUG = 0,
34 /// MEM_TASK1,
35 /// MEM_TASK2,
36 /// MEM_MAX_TASKS
37 /// };
38 ///
39 /// static SYS_MemoryUser theMemoryUsers[MEM_MAX_TASKS] = {
40 /// SYS_MemoryUser("Debug),
41 /// SYS_MemoryUser("Task One"),
42 /// SYS_MemoryUser("Task Two"),
43 /// };
44 ///
45 /// static SYS_MemoryTable theMemoryTable(theMemoryUsers,
46 /// sizeof(theMemoryUsers)/sizeof(SYS_MemoryTable));
47 ///
48 /// int
49 /// main(int argc, char *argv[])
50 /// {
51 /// UT_WorkBuffer stats;
52 /// void *mem;
53 /// mem = SYS_Memory::Malloc(theMemoryTable, MEM_TASK1, 128);
54 /// mem = SYS_Memory::Realloc(theMemoryTable, MEM_TASK1, mem, 128, 256);
55 /// SYS_Memory::Free(theMemoryTable, MEM_TASK1, mem, 256);
56 /// UT_Memory::printTable(stats, theMemoryTable);
57 /// cout << stats.buffer();
58 /// return 0;
59 /// }
60 ///
61 
63 public:
64  SYS_MemoryUser(const char *label)
65  : myUsed(0)
66  , myPeak(0)
67  {
68  // WARNING: The label is a reference to the string. It's not hardened
69  myLabel = label;
70  }
71 
73  : myUsed(rhs.myUsed.relaxedLoad())
74  , myPeak(rhs.myPeak.relaxedLoad())
75  {
76  myLabel = rhs.myLabel;
77  }
78 
79  const char *getLabel() const { return myLabel; }
80  size_t getUsed() const { return myUsed; }
81  size_t getPeak() const { return myPeak; }
82 
83  void inc(size_t amount)
84  {
85  myPeak.maximum(myUsed.add(amount));
86  }
87  void dec(size_t amount)
88  {
89  myUsed.add(-amount);
90  }
91 
92 private:
93  const char *myLabel;
94  SYS_AtomicCounter myUsed;
95  SYS_AtomicCounter myPeak;
96 };
97 
99 public:
100  SYS_MemoryTable(SYS_MemoryUser *user_list, int number_of_users)
101  {
102  myTable = user_list;
103  mySize = number_of_users;
104  }
105 
106  SYS_MemoryUser &getUser(int index) { return myTable[index]; }
107  const SYS_MemoryUser &getUser(int index) const { return myTable[index]; }
108 
109  int entries() const { return mySize; }
110  size_t getUsed() const;
111  size_t getPeak() const;
112 
113  void inc(int user, size_t amount)
114  {
115  myTable[user].inc(amount);
116  }
117  void dec(int user, size_t amount)
118  {
119  myTable[user].dec(amount);
120  }
121 
122 private:
123  SYS_MemoryUser *myTable;
124  int mySize;
125 };
126 
128 public:
129  /// Allocate memory and track the usage.
130  /// This method will return a null pointer if the size requested is equal
131  /// to 0.
132  static void *Malloc(SYS_MemoryTable &table,
133  int which_entry,
134  size_t amount)
135  {
136  if (amount)
137  {
138  table.inc(which_entry, amount);
139  return malloc(amount);
140  }
141  return 0;
142  }
143  /// Allocate memory and track the usage. The memory will filled with zero.
144  /// This method will return a null pointer if the size requested is equal
145  /// to 0.
146  static void *Calloc(SYS_MemoryTable &table,
147  int which_entry,
148  size_t amount)
149  {
150  if (amount)
151  {
152  table.inc(which_entry, amount);
153  return calloc(1, amount);
154  }
155  return 0;
156  }
157  /// Re-allocate a previously allocated block. This method handles
158  /// the case where the initial block has not been allocated (i.e. is a
159  /// null pointer).
160  /// This method will return a null pointer if the new_amount size requested
161  /// is equal to 0.
162  static void *Realloc(SYS_MemoryTable &table,
163  int which_entry,
164  void *original_memory,
165  size_t old_amount,
166  size_t new_amount)
167  {
168  void *mem;
169  if (new_amount)
170  {
171  if (original_memory)
172  {
173  // Do it as two separate operations since size_t
174  // may be an unsigned and taking the delta may
175  // cause an overflow.
176  table.dec(which_entry, old_amount);
177  table.inc(which_entry, new_amount);
178  mem = realloc(original_memory, new_amount);
179  }
180  else
181  {
182  table.inc(which_entry, new_amount);
183  mem = malloc(new_amount);
184  }
185  }
186  else
187  {
188  mem = 0;
189  if (original_memory)
190  {
191  table.dec(which_entry, old_amount);
192  free(original_memory);
193  }
194  }
195  return mem;
196  }
197 
198  /// Free an allocated block (tracking the memory usage).
199  /// If a null pointer is passed in, no tracking will be done. Thus, it's
200  /// safe to pass in a non-zero size without a valid pointer (and not
201  /// destroy the tracking process).
202  static void Free(SYS_MemoryTable &table,
203  int which_entry,
204  void *memory,
205  size_t amount)
206  {
207  if (memory)
208  {
209  table.dec(which_entry, amount);
210  free(memory);
211  }
212  }
213 
214  /// Track a memory acquisition that wasn't performed by this class.
215  static void acquire(SYS_MemoryTable &table,
216  int which_entry,
217  size_t amount)
218  {
219  table.inc(which_entry, amount);
220  }
221  /// Track a memory free that wasn't performed by this class.
222  static void release(SYS_MemoryTable &table,
223  int which_entry,
224  size_t amount)
225  {
226  table.dec(which_entry, amount);
227  }
228 };
229 
230 /// When implementing in a different library, the following macro can be used
231 /// to implement a localized interface. For example, we might have
232 /// SYS_MEMORY_SUBCLASS(, GU, theGUMemoryTable)
233 /// or
234 /// class GU_Memory {
235 /// public:
236 /// SYS_MEMORY_SUBCLASS(static, GU, myMemoryTable)
237 /// private:
238 /// static SYS_MemoryTable myMemoryTable;
239 /// };
240 ///
241 #define SYS_MEMORY_SUBCLASS(STATIC, prefix, table) \
242  STATIC void *prefix##Malloc(int i, size_t amount) \
243  { return SYS_Memory::Malloc(table, i, amount); } \
244  STATIC void *prefix##Calloc(int i, size_t amount) \
245  { return SYS_Memory::Calloc(table, i, amount); } \
246  STATIC void *prefix##Realloc(int i, void *m, size_t o, size_t n) \
247  { return SYS_Memory::Realloc(table, i, m, o, n); } \
248  STATIC void prefix##Free(int i, void *m, size_t amount) \
249  { SYS_Memory::Free(table, i, m, amount); } \
250  STATIC void prefix##acquire(int i, size_t amount) \
251  { SYS_Memory::acquire(table, i, amount); } \
252  STATIC void prefix##release(int i, size_t amount) \
253  { SYS_Memory::release(table, i, amount); } \
254  static inline SYS_MemoryTable &prefix##getTable() { return table; }
255 
256 ///
257 /// Convenience function to print memory in a consistent format (i.e. 12.3 KB).
258 /// To print "18446744073709551616.00 MB" requires 27 characters. There are 5
259 /// extra characters for good measure in SYS_MEMPRINTSIZE
260 #define SYS_MEMPRINTSIZE 32
261 SYS_API void SYSprintMemory(char buf[SYS_MEMPRINTSIZE], int64 memory,
262  int field_width=-1);
263 
264 #endif
SYS_API void SYSprintMemory(char buf[SYS_MEMPRINTSIZE], int64 memory, int field_width=-1)
GLuint GLsizei const GLchar * label
Definition: glcorearb.h:2544
static void release(SYS_MemoryTable &table, int which_entry, size_t amount)
Track a memory free that wasn't performed by this class.
Definition: SYS_Memory.h:222
void dec(size_t amount)
Definition: SYS_Memory.h:87
SYS_MemoryUser(const SYS_MemoryUser &rhs)
Definition: SYS_Memory.h:72
const SYS_MemoryUser & getUser(int index) const
Definition: SYS_Memory.h:107
long long int64
Definition: SYS_Types.h:106
static void Free(SYS_MemoryTable &table, int which_entry, void *memory, size_t amount)
Definition: SYS_Memory.h:202
SYS_MemoryUser & getUser(int index)
Definition: SYS_Memory.h:106
static void * Realloc(SYS_MemoryTable &table, int which_entry, void *original_memory, size_t old_amount, size_t new_amount)
Definition: SYS_Memory.h:162
static void * Calloc(SYS_MemoryTable &table, int which_entry, size_t amount)
Definition: SYS_Memory.h:146
void inc(int user, size_t amount)
Definition: SYS_Memory.h:113
size_t getUsed() const
Definition: SYS_Memory.h:80
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:2539
SYS_MemoryUser(const char *label)
Definition: SYS_Memory.h:64
SYS_MemoryTable(SYS_MemoryUser *user_list, int number_of_users)
Definition: SYS_Memory.h:100
static void acquire(SYS_MemoryTable &table, int which_entry, size_t amount)
Track a memory acquisition that wasn't performed by this class.
Definition: SYS_Memory.h:215
GLuint index
Definition: glcorearb.h:785
int entries() const
Definition: SYS_Memory.h:109
static void * Malloc(SYS_MemoryTable &table, int which_entry, size_t amount)
Definition: SYS_Memory.h:132
const char * getLabel() const
Definition: SYS_Memory.h:79
size_t getPeak() const
Definition: SYS_Memory.h:81
#define SYS_API
Definition: SYS_API.h:11
void inc(size_t amount)
Definition: SYS_Memory.h:83
void dec(int user, size_t amount)
Definition: SYS_Memory.h:117
#define SYS_MEMPRINTSIZE
Definition: SYS_Memory.h:260