rogue25b2/gods/
rogue25b2/player/
rogue25b2/space/planets/
rogue25b2/space/prototypes/
rogue25b2/space/ships/
rogue25b2/src/
/***************************************************************************\
[*]    __     __  ___                ___  | LexiMUD is a C++ MUD codebase [*]
[*]   / /  ___\ \/ (_) /\/\  /\ /\  /   \ |        for Sci-Fi MUDs        [*]
[*]  / /  / _ \\  /| |/    \/ / \ \/ /\ / | Copyright(C) 1997-1999        [*]
[*] / /__|  __//  \| / /\/\ \ \_/ / /_//  | All rights reserved           [*]
[*] \____/\___/_/\_\_\/    \/\___/___,'   | Chris Jacobson (FearItself)   [*]
[*]      A Creation of the AvP Team!      | fear@technologist.com         [*]
[-]---------------------------------------+-------------------------------[-]
[*] Advanced Buffer System by George Greer, Copyright (C) 1998-99         [*]
[-]-----------------------------------------------------------------------[-]
[*] File : buffer.h                                                       [*]
[*] Usage: Advanced Buffer System                                         [*]
\***************************************************************************/

#ifndef __BUFFER_H__
#define __BUFFER_H__


#include "types.h"
#include "internal.defs.h"


//	CONFIGURABLES (aka, The place to shoot your own foot.) :)
//	---------------------------------------------------------
#define BUFFER_MEMORY				0	//	Use buffer system for CREATE
#define USE_CIRCLE_BUFFERS			0	//	Include original CircleMUD buffers
#ifdef macintosh
#define BUFFER_THREADED				0	//	Use threads
#else
#define BUFFER_THREADED				0	//	Use threads
#endif

class Buffer {
public:
	enum Type {			//	Types for the memory to allocate.
		tBuffer,		//	Stack type memory.
		tPersist,		//	A buffer that doesn't time out.
		tMalloc			//	A malloc() memory tracker.
	};
	
//protected:
					Buffer(size_t size, Type type);
					~Buffer(void);
	
	Type			Clear(void);
	void			Remove(void);
	int				Used(void);
	int				Magnitude(void);
	
	SInt8			magic;			//	Have we been trashed?
	Type			type;			//	What type of buffer are we?
	size_t			req_size;		//	How much did the function request?
	const size_t	size;			//	How large is this buffer realy?
	char *			data;			//	The buffer passed back to functions
public:
	Buffer *		next;			//	Next structure
	
#if BUFFER_THREADED
	enum tLock {
		lockNone		= 0,
		lockAcquire		= 1 << 0,
		lockWillClear	= 1 << 1,
		lockWillFree	= 1 << 2,
		lockWillRemove	= 1 << 3
	} locked;						//	Don't touch this item, we're locked.
	
	void Lock(tLock type, const char *func, UInt16 line);
	void Unlock(const char *func, UInt16 line);
	
	static void *ThreadFunc(void *);
	static void ListLock(const char *func, UInt16 line);
	static void ListUnlock(const char *func, UInt16 line);
#endif
	
public:
	union {
		SInt32			life;		//	An idle counter to free unused ones.	(B)
		const char *	var;		//	Name of variable allocated to.			(M)
	};
	SInt16			line;			//	What source code line is using this.
	const char	*	who;			//	Name of the function using this
	
	void			Check(void);
	
public:
	static void		Init(void);
	static void		Exit(void);
	
	static void		Reboot(void);
	
	static Buffer **Head(Type type);
//	static void		Lock(Type type);
//	static void		Unlock(Type type);
	
	static Buffer *	Find(const char *given, Type type);
	static Buffer *	FindAvailable(size_t size);
	static void		Detach(const char *data, Type type,
			const char *func, const int line_n);
	static char *	Acquire(size_t size, Type type,
			const char *varname, const char *who, UInt16 line);
	
	static void		ReleaseAll(void);
	
	static Buffer **buf;
	static Buffer **mem;
	
	static Flags	options;
	static const char *const optionsDesc[];
	
private:
	static void		Decrement(void);
	static void		ReleaseOld(void);
	static void		FreeOld(void);
};


inline Buffer **Buffer::Head(Buffer::Type type) {
	return (type == Buffer::tMalloc ? mem : buf);
}


/*
 * These macros neatly pass the required information without breaking the
 * rest of the code.  The 'get_buffer()' code should be used for a temporary
 * memory chunk such as the current CircleMUD 'buf,' 'buf1,' and 'buf2'
 * variables.  Remember to use 'release_buffer()' to give up the requested
 * buffer when finished with it.  'release_my_buffers()' may be used in
 * functions with a lot of return statements but it is _not_ encouraged.
 * 'get_memory()' and 'release_memory()' should only be used for memory that
 * you always want handled here regardless of BUFFER_MEMORY.
 */
#define get_buffer(a)		Buffer::Acquire((a), Buffer::tBuffer, NULL, __FUNCTION__, __LINE__)
#define get_memory(a)		Buffer::Acquire((a), Buffer::tMalloc, NULL, __FUNCTION__, __LINE__)
#define release_buffer(a)	do { Buffer::Detach((a), Buffer::tBuffer, __FUNCTION__, __LINE__); (a) = NULL; } while(0)
#define release_memory(a)	do { Buffer::Detach((a), Buffer::tMalloc, __FUNCTION__, __LINE__); (a) = NULL; } while(0)
#define release_my_buffers()	detach_my_buffers(__FUNCTION__, __LINE__)


//	Public functions for outside use.
#if 0 /* BUFFER_SNPRINTF */
buffer *str_cpy(buffer *d, buffer*s);
int bprintf(buffer *buf, const char *format, ...);
#endif
#if BUFFER_MEMORY
void *debug_calloc(size_t number, size_t size, const char *var, const char *func, int line);
void *debug_realloc(void *ptr, size_t size, const char *var, const char *func, int line);
void debug_free(void *ptr, const char *func, ush_int line);
char *debug_str_dup(const char *txt, const char *var, const char *func, ush_int line);
#endif
void show_buffers(CHAR_DATA *ch, Buffer::Type type, int display_type);

#endif