1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
|
/*
* PARSEC HEADER: e_relist.h
*/
#ifndef _E_RELIST_H_
#define _E_RELIST_H_
// forward decls --------------------------------------------------------------
//
class E_SimShipState;
class E_SimPlayerInfo;
//FIXME: this should be merged with DEBUG.C
// easy access to the singleton -----------------------------------------------
//
#define TheMemoryManager UTL_MemoryManager::GetMemoryManager()
// set these wisely
#define MEMMAN_HASH_TABLE_SIZE 1001
#define HASH_POINTER_ADDRESS(x) ( ((size_t)(x)) % MEMMAN_HASH_TABLE_SIZE )
// struct defining a entry in the memory manager ------------------------------
//
class UTL_MemEntry
{
protected:
UTL_MemEntry* m_pNext;
void* m_p;
const char* m_descr1;
const char* m_descr2;
public:
UTL_MemEntry( void* p = NULL, const char* descr1 = NULL, const char* descr2 = NULL ) :
m_pNext( NULL ),
m_p( p ),
m_descr1( descr1 ),
m_descr2( descr2 )
{
}
friend class UTL_MemoryManager;
};
// memory manager -------------------------------------------------------------
//
class UTL_MemoryManager
{
protected:
UTL_MemEntry* m_HashTable[ MEMMAN_HASH_TABLE_SIZE ];
UTL_MemoryManager()
{
for( int nEntry = 0; nEntry < MEMMAN_HASH_TABLE_SIZE; nEntry++ ) {
m_HashTable[ nEntry ] = NULL;
}
}
~UTL_MemoryManager()
{
CheckLeaks();
}
public:
// SINGLETON pattern
static UTL_MemoryManager* GetMemoryManager()
{
static UTL_MemoryManager _TheMemoryManager;
return &_TheMemoryManager;
}
// add a pointer for tracking
int AddTracking( void* p, const char* descr1, const char* descr2 )
{
//MSGOUT( "UTL_MemoryManager::AddTracking(): %x, %s, %s", p, descr1, descr2 );
// get hash key
size_t htid = HASH_POINTER_ADDRESS( p );
// search hash table for already existing entry
for ( UTL_MemEntry* scan = m_HashTable[ htid ]; scan != NULL; scan = scan->m_pNext ) {
if ( scan->m_p == p ) {
// issue warning
MSGOUT( "UTL_MemManager::AddTracking(): duplicate call for pointer %x (%s, %s).", p, descr1, descr2 );
return FALSE;
}
}
// create new entry & prepend to list
UTL_MemEntry* newentry = new UTL_MemEntry( p, descr1, descr2 );
newentry->m_pNext = m_HashTable[ htid ];
m_HashTable[ htid ] = newentry;
return TRUE;
}
// remove a pointer from tracking
int RemoveTracking( void* p )
{
// get hash key
size_t htid = HASH_POINTER_ADDRESS( p );
UTL_MemEntry* scan = m_HashTable[ htid ];
if ( scan != NULL ) {
// check for head removal
if ( scan->m_p == p ) {
m_HashTable[ htid ] = scan->m_pNext;
//MSGOUT( "UTL_MemoryManager::RemoveTracking(): %x, %s, %s", scan->m_p, scan->m_descr1, scan->m_descr2 );
delete scan;
return TRUE;
}
// setup iteration
UTL_MemEntry* prev = scan;
scan = scan->m_pNext;
for ( ; scan != NULL; scan = scan->m_pNext ) {
if ( scan->m_p == p ) {
// unlink from list
prev->m_pNext = scan->m_pNext;
//MSGOUT( "UTL_MemoryManager::RemoveTracking(): %x, %s, %s", scan->m_p, scan->m_descr1, scan->m_descr2 );
delete scan;
return TRUE;
}
}
}
// issue warning
MSGOUT( "UTL_MemManager::RemoveTracking(): tracking entry for pointer %x not found.", p );
return FALSE;
}
// dump all pointers we still track
void CheckLeaks()
{
for( int nEntry = 0; nEntry < MEMMAN_HASH_TABLE_SIZE; nEntry++ ) {
for( UTL_MemEntry* scan = m_HashTable[ nEntry ]; scan != NULL; scan = scan->m_pNext ) {
MSGOUT( "UTL_MemManager::CheckLeaks(): leaked pointer %x (%s, %s)", scan->m_p, scan->m_descr1, scan->m_descr2 );
}
}
}
};
// class holding a remote event list ------------------------------------------
//
class E_REList
{
protected:
char* m_data;
char* m_CurPos;
size_t m_Avail;
size_t m_nMaxSize;
// reference counting stuff
int m_nRefCount;
~E_REList();
E_REList();
E_REList( size_t size );
public:
// reference counting stuff
static E_REList* CreateAndAddRef( size_t size )
{
E_REList* relist = new E_REList;
relist->AddRef();
#ifdef PARSEC_DEBUG
TheMemoryManager->AddTracking( (void*)relist, __FILE__, "E_REList::CreateAndAddRef()" );
#endif // PARSEC_DEBUG
relist->Init( size );
return relist;
}
void AddRef() { m_nRefCount++; }
void Release()
{
m_nRefCount--;
if ( m_nRefCount == 0 ) {
#ifdef PARSEC_DEBUG
TheMemoryManager->RemoveTracking( (void*)this );
#endif // PARSEC_DEBUG
delete this;
}
}
// init the remote event list
void Init( size_t size );
// return the internal data of the remote event list
RE_Header* GetData() { return (RE_Header*)m_data; }
// return the size of the RE list
size_t GetSize() { return (size_t)( m_CurPos - m_data ); }
// clear remote event list
int Clear();
// append a remote event list
int AppendList( RE_Header* relist );
// append a E_REList
int AppendList( E_REList* relist );
// append a remote event
size_t AppendEvent( RE_Header* re, size_t size );
// check whether we have any remote events in the list
int HasEvents()
{
return ( ( (RE_Header*) m_data)->RE_Type != RE_EMPTY );
}
// write to an external remote event list
size_t WriteTo( RE_Header* dst, size_t maxsize, int allow_truncate );
// check if enough space in RE_List for specified remote event
int RmEvAllowed( int re_type );
// dump contents of RE list
void Dump();
// allocate space for a specific RE
RE_Header* NET_Allocate( int retype );
// insert state sync remote event
int RmEvStateSync( byte statekey, byte stateval );
// append a RE_OwnerSection event
int NET_Append_RE_OwnerSection( int ownerid );
// insert command info into remote event list
int NET_Append_RE_CommandInfo( const char* commandstring );
// append a RE_PlayerAndShipStatus event
//FIXME: GAMECODE
//FIXME: consolidate naming with RmEv<remote-event-name>
int NET_Append_RE_PlayerAndShipStatus( int nClientID, E_SimPlayerInfo* pSimPlayerInfo, E_SimShipState* pSimShipState, refframe_t CurRefFrame, bool_t bUpdatePropsOnly );
// append a RE_GameState
//FIXME: GAMECODE
int NET_Append_RE_GameState();
// append a RE_KillStats event
//FIXME: GAMECODE
int NET_Append_RE_KillStats();
// append a RE_CreateLaser event
//FIXME: GAMECODE
int NET_Append_RE_CreateLaser( const LaserObject* laserpo );
// append a RE_CreateMissile event
//FIXME: GAMECODE
int NET_Append_RE_CreateMissile( const MissileObject *missilepo, dword targetobjid );
// Append a RE_CreateExtra event
int NET_Append_RE_CreateExtra( const ExtraObject *extrapo );
// append a RE_KillOjbect event
//FIXME: GAMECODE
int NET_Append_RE_KillObject( dword objectid, byte listno );
// append a RE_CreateExtra2 event
//FIXME: GAMECODE
int NET_Append_RE_CreateExtra2( const ExtraObject *extrapo );
// append a RE_IPv4ServerInfo event
int NET_Append_RE_IPv4ServerInfo( node_t* node, word nServerID, int xpos, int ypos, word flags );
// append a RE_ServerLinkInfo event
int NET_Append_RE_ServerLinkInfo( word nServerID_1, word nServerID_2, word flags );
// append a RE_MapObject
int NET_Append_RE_MapObject( int map_objectid, char* name, int xpos, int ypos, int w, int h, char* texname );
//Append a Particle RE (energy fields, megashield...etc)
int NET_Append_RE_ParticleObject( int type, const Vertex3& origin );
// determine the size of a remote-event list
static size_t DetermineListSize( RE_Header* relist )
{
ASSERT( relist != NULL );
size_t lsize = 0;
// process remote event list
while ( relist->RE_Type != RE_EMPTY ) {
// sum up size of all remote events
size_t resize = RmEvGetSize( relist );
lsize += resize;
// advance to next event
ASSERT( ( relist->RE_BlockSize == RE_BLOCKSIZE_INVALID ) ||
( relist->RE_BlockSize == resize ) );
relist = (RE_Header *) ( (char *) relist + resize );
}
// include size of RE list termination
lsize += sizeof( dword );
return lsize;
}
// determine size of remote event
static size_t RmEvGetSize( RE_Header *relist );
// determine size of remote event from type
static size_t RmEvGetSizeFromType( byte retype );
// check whether the remote event list is well formed
static int IsWellFormed( RE_Header *relist );
// return the max. size of the RE list that can fit in one external packet
static size_t GetMaxSizeInPacket();
// validate the RE according to all bounds
static int ValidateRE( RE_Header* relist, size_t size );
protected:
};
#define NET_RmEvList_GetSize E_REList::DetermineListSize
#define NET_RmEvList_IsWellFormed E_REList::IsWellFormed
#endif // _E_RELIST_H_
|