--- deliantra/server/include/util.h 2008/04/02 11:13:55 1.66 +++ deliantra/server/include/util.h 2008/05/03 11:14:50 1.73 @@ -22,8 +22,9 @@ #ifndef UTIL_H__ #define UTIL_H__ -#define DEBUG_SALLOC 0 -#define PREFER_MALLOC 0 +#define DEBUG_POISON 0x00 // poison memory before freeing it if != 0 +#define DEBUG_SALLOC 0 // add a debug wrapper around all sallocs +#define PREFER_MALLOC 0 // use malloc and not the slice allocator #if __GNUC__ >= 3 # define is_constant(c) __builtin_constant_p (c) @@ -64,6 +65,10 @@ void *g_slice_alloc (unsigned long size); void *g_slice_alloc0 (unsigned long size); void g_slice_free1 (unsigned long size, void *ptr); +#elif PREFER_MALLOC +# define g_slice_alloc0(s) calloc (1, (s)) +# define g_slice_alloc(s) malloc ((s)) +# define g_slice_free1(s,p) free ((p)) #endif // use C0X decltype for auto declarations until ISO C++ sanctifies them (if ever) @@ -190,7 +195,44 @@ return ((d - 1) & 7) + 1; } -extern size_t slice_alloc; // statistics +extern ssize_t slice_alloc; // statistics + +void *salloc_ (int n) throw (std::bad_alloc); +void *salloc_ (int n, void *src) throw (std::bad_alloc); + +// strictly the same as g_slice_alloc, but never returns 0 +template +inline T *salloc (int n = 1) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T)); } + +// also copies src into the new area, like "memdup" +// if src is 0, clears the memory +template +inline T *salloc (int n, T *src) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T), (void *)src); } + +// clears the memory +template +inline T *salloc0(int n = 1) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T), 0); } + +// for symmetry +template +inline void sfree (T *ptr, int n = 1) throw () +{ + if (expect_true (ptr)) + { + slice_alloc -= n * sizeof (T); + if (DEBUG_POISON) memset (ptr, DEBUG_POISON, n * sizeof (T)); + g_slice_free1 (n * sizeof (T), (void *)ptr); + assert (slice_alloc >= 0);//D + } +} + +// nulls the pointer +template +inline void sfree0 (T *&ptr, int n = 1) throw () +{ + sfree (ptr, n); + ptr = 0; +} // makes dynamically allocated objects zero-initialised struct zero_initialised @@ -203,56 +245,53 @@ void *operator new (size_t s) { - slice_alloc += s; - return g_slice_alloc0 (s); + return salloc0 (s); } void *operator new[] (size_t s) { - slice_alloc += s; - return g_slice_alloc0 (s); + return salloc0 (s); } void operator delete (void *p, size_t s) { - slice_alloc -= s; - g_slice_free1 (s, p); + sfree ((char *)p, s); } void operator delete[] (void *p, size_t s) { - slice_alloc -= s; - g_slice_free1 (s, p); + sfree ((char *)p, s); } }; -void *salloc_ (int n) throw (std::bad_alloc); -void *salloc_ (int n, void *src) throw (std::bad_alloc); +// makes dynamically allocated objects zero-initialised +struct slice_allocated +{ + void *operator new (size_t s, void *p) + { + return p; + } -// strictly the same as g_slice_alloc, but never returns 0 -template -inline T *salloc (int n = 1) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T)); } + void *operator new (size_t s) + { + return salloc (s); + } -// also copies src into the new area, like "memdup" -// if src is 0, clears the memory -template -inline T *salloc (int n, T *src) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T), (void *)src); } + void *operator new[] (size_t s) + { + return salloc (s); + } -// clears the memory -template -inline T *salloc0(int n = 1) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T), 0); } + void operator delete (void *p, size_t s) + { + sfree ((char *)p, s); + } -// for symmetry -template -inline void sfree (T *ptr, int n = 1) throw () -{ -#if PREFER_MALLOC - free (ptr); -#else - slice_alloc -= n * sizeof (T); - g_slice_free1 (n * sizeof (T), (void *)ptr); -#endif -} + void operator delete[] (void *p, size_t s) + { + sfree ((char *)p, s); + } +}; // a STL-compatible allocator that uses g_slice // boy, this is verbose @@ -608,8 +647,15 @@ #endif #define SMUTEX(name) smutex name = SMUTEX_INITIALISER -#define SMUTEX_LOCK(name) pthread_mutex_lock (&(name)) +#define SMUTEX_LOCK(name) pthread_mutex_lock (&(name)) #define SMUTEX_UNLOCK(name) pthread_mutex_unlock (&(name)) +typedef pthread_cond_t scond; + +#define SCOND(name) scond name = PTHREAD_COND_INITIALIZER +#define SCOND_SIGNAL(name) pthread_cond_signal (&(name)) +#define SCOND_BROADCAST(name) pthread_cond_broadcast (&(name)) +#define SCOND_WAIT(name,mutex) pthread_cond_wait (&(name), &(mutex)) + #endif