core/systems/HandleSys.h
author David Anderson <dvander@alliedmods.net>
Thu Jan 04 02:08:27 2007 +0000 (2007-01-04)
changeset 262 de0e374ffa47
parent 259 ca9b124a2544
child 283 c3d54680969a
permissions -rw-r--r--
restructure of HandleSys admin permissions and interface
removal of HandleSys helper functions
removed useless BaseContext stuff from Engine
put SourceMod specific stuff in BaseContext
cleaned up broken Handle code
dvander@218
     1
#ifndef _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
dvander@218
     2
#define _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
dvander@218
     3
dvander@218
     4
#include <IHandleSys.h>
dvander@218
     5
#include "sm_globals.h"
dvander@218
     6
#include "sm_trie.h"
dvander@218
     7
#include "sourcemod.h"
dvander@218
     8
#include "sm_memtable.h"
dvander@218
     9
dvander@222
    10
#define HANDLESYS_MAX_HANDLES		(1<<14)
dvander@218
    11
#define HANDLESYS_MAX_TYPES			(1<<9)
dvander@218
    12
#define HANDLESYS_MAX_SUBTYPES		0xF
dvander@218
    13
#define HANDLESYS_SUBTYPE_MASK		0xF
dvander@218
    14
#define HANDLESYS_TYPEARRAY_SIZE	(HANDLESYS_MAX_TYPES * (HANDLESYS_MAX_SUBTYPES + 1))
dvander@218
    15
#define HANDLESYS_MAX_SERIALS		0xFFFF
dvander@218
    16
#define HANDLESYS_SERIAL_MASK		0xFFFF0000
dvander@218
    17
#define HANDLESYS_HANDLE_MASK		0x0000FFFF
dvander@218
    18
dvander@229
    19
/**
dvander@229
    20
 *   The QHandle is a nasty structure that compacts the handle system into a big vector.
dvander@229
    21
 * The members of the vector each encapsulate one Handle, however, they also act as nodes
dvander@229
    22
 * in an inlined linked list and an inlined vector.
dvander@229
    23
 *
dvander@229
    24
 *   The first of these lists is the 'freeID' list.  Each node from 1 to N (where N
dvander@229
    25
 * is the number of free nodes) has a 'freeID' that specifies a free Handle ID.  This
dvander@229
    26
 * is a quick hack to get around allocating a second base vector.
dvander@229
    27
 *
dvander@229
    28
 *   The second vector is the identity linked list.  An identity has its own handle, so
dvander@229
    29
 * these handles are used as sentinel nodes for index linking.  They point to the first and last
dvander@229
    30
 * index into the handle array.  Each subsequent Handle who is owned by that indentity is mapped into
dvander@229
    31
 * that list.  This lets owning identities be unloaded in O(n) time.
dvander@229
    32
 *
dvander@229
    33
 *   Eventually, there may be a third list for type chains.
dvander@229
    34
 */
dvander@229
    35
dvander@229
    36
enum HandleSet
dvander@229
    37
{
dvander@229
    38
	HandleSet_None = 0,
dvander@259
    39
	HandleSet_Used,			/* The Handle is in use */
dvander@259
    40
	HandleSet_Freed,		/* The "master" Handle of a clone chain is freed */
dvander@259
    41
	HandleSet_Identity,		/* The Handle is a special identity */
dvander@229
    42
};
dvander@229
    43
dvander@218
    44
struct QHandle
dvander@218
    45
{
dvander@222
    46
	HandleType_t type;			/* Handle type */
dvander@222
    47
	void *object;				/* Unmaintained object pointer */
dvander@229
    48
	IdentityToken_t *owner;		/* Identity of object which owns this */
dvander@222
    49
	unsigned int serial;		/* Serial no. for sanity checking */
dvander@222
    50
	unsigned int refcount;		/* Reference count for safe destruction */
dvander@262
    51
	unsigned int clone;			/* If non-zero, this is our cloned parent index */
dvander@229
    52
	HandleSet set;				/* Information about the handle's state */
dvander@229
    53
	/* The following variables are unrelated to the Handle array, and used 
dvander@229
    54
	 * as an inlined chain of information */
dvander@229
    55
	unsigned int freeID;		/* ID of a free handle in the free handle chain */
dvander@229
    56
	/* Indexes into the handle array for owner membership.
dvander@229
    57
	 * For identity roots, these are treated as the head/tail. */
dvander@229
    58
	unsigned int ch_prev;		/* chained previous handle or HEAD */
dvander@229
    59
	unsigned int ch_next;		/* chained next handle or TAIL */
dvander@218
    60
};
dvander@218
    61
dvander@218
    62
struct QHandleType
dvander@218
    63
{
dvander@218
    64
	IHandleTypeDispatch *dispatch;
dvander@218
    65
	unsigned int freeID;
dvander@218
    66
	unsigned int children;
dvander@262
    67
	TypeAccess typeSec;
dvander@262
    68
	HandleAccess hndlSec;
dvander@218
    69
	unsigned int opened;
dvander@218
    70
	int nameIdx;
dvander@218
    71
};
dvander@218
    72
dvander@218
    73
class HandleSystem : 
dvander@218
    74
	public IHandleSys
dvander@218
    75
{
dvander@229
    76
	friend HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index);
dvander@229
    77
	friend class ShareSystem;
dvander@218
    78
public:
dvander@218
    79
	HandleSystem();
dvander@218
    80
	~HandleSystem();
dvander@218
    81
public: //IHandleSystem
dvander@262
    82
dvander@262
    83
	HandleType_t CreateType(const char *name,
dvander@262
    84
		IHandleTypeDispatch *dispatch,
dvander@262
    85
		HandleType_t parent,
dvander@262
    86
		const TypeAccess *typeAccess,
dvander@262
    87
		const HandleAccess *hndlAccess,
dvander@262
    88
		IdentityToken_t *ident,
dvander@262
    89
		HandleError *err);
dvander@262
    90
dvander@229
    91
	bool RemoveType(HandleType_t type, IdentityToken_t *ident);
dvander@262
    92
dvander@218
    93
	bool FindHandleType(const char *name, HandleType_t *type);
dvander@262
    94
dvander@218
    95
	Handle_t CreateHandle(HandleType_t type, 
dvander@262
    96
		void *object,
dvander@262
    97
		IdentityToken_t *owner,
dvander@262
    98
		IdentityToken_t *ident,
dvander@262
    99
		HandleError *err);
dvander@262
   100
	HandleError FreeHandle(Handle_t handle, const HandleSecurity *pSecurity);
dvander@262
   101
dvander@262
   102
	HandleError CloneHandle(Handle_t handle, 
dvander@262
   103
		Handle_t *newhandle, 
dvander@262
   104
		IdentityToken_t *newOwner,
dvander@262
   105
		const HandleSecurity *pSecurity);
dvander@262
   106
dvander@262
   107
	HandleError ReadHandle(Handle_t handle, 
dvander@262
   108
		HandleType_t type, 
dvander@262
   109
		const HandleSecurity *pSecurity,
dvander@262
   110
		void **object);
dvander@262
   111
dvander@262
   112
	bool InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess);
dvander@262
   113
dvander@229
   114
	bool TypeCheck(HandleType_t intype, HandleType_t outtype);
dvander@229
   115
protected:
dvander@222
   116
	/**
dvander@222
   117
	 * Decodes a handle with sanity and security checking.
dvander@222
   118
	 */
dvander@222
   119
	HandleError GetHandle(Handle_t handle, 
dvander@229
   120
						  IdentityToken_t *ident, 
dvander@222
   121
						  QHandle **pHandle, 
dvander@222
   122
						  unsigned int *index,
dvander@259
   123
						  bool ignoreFree=false);
dvander@222
   124
dvander@222
   125
	/**
dvander@222
   126
	 * Creates a basic handle and sets its reference count to 1.
dvander@222
   127
	 * Does not do any type or security checking.
dvander@222
   128
	 */
dvander@229
   129
	HandleError MakePrimHandle(HandleType_t type, 
dvander@229
   130
							   QHandle **pHandle, 
dvander@229
   131
							   unsigned int *index, 
dvander@229
   132
							   HandleType_t *handle,
dvander@229
   133
							   IdentityToken_t *owner);
dvander@222
   134
dvander@222
   135
	/**
dvander@229
   136
	 * Frees a primitive handle.  Does no object freeing, only reference count, bookkeepping, 
dvander@229
   137
	 * and linked list maintenance.
dvander@222
   138
	 */
dvander@222
   139
	void ReleasePrimHandle(unsigned int index);
dvander@229
   140
dvander@229
   141
	/**
dvander@229
   142
	 * Sets the security owner of a type
dvander@229
   143
	 */
dvander@229
   144
	void SetTypeSecurityOwner(HandleType_t type, IdentityToken_t *pToken);
dvander@229
   145
dvander@229
   146
	/** 
dvander@229
   147
	 * Marks a handle as an identity.
dvander@229
   148
	 * This prevents it from being tampered with by outside stuff
dvander@229
   149
	 */
dvander@229
   150
	void MarkHandleAsIdentity(Handle_t handle);
dvander@262
   151
dvander@262
   152
	bool CheckAccess(QHandle *pHandle, HandleAccessRight right, const HandleSecurity *pSecurity);
dvander@222
   153
private:
dvander@218
   154
	QHandle *m_Handles;
dvander@218
   155
	QHandleType *m_Types;
dvander@218
   156
	Trie *m_TypeLookup;
dvander@218
   157
	unsigned int m_TypeTail;
dvander@218
   158
	unsigned int m_FreeTypes;
dvander@218
   159
	unsigned int m_HandleTail;
dvander@218
   160
	unsigned int m_FreeHandles;
dvander@218
   161
	unsigned int m_HSerial;
dvander@218
   162
	BaseStringTable *m_strtab;
dvander@218
   163
};
dvander@218
   164
dvander@218
   165
extern HandleSystem g_HandleSys;
dvander@218
   166
dvander@218
   167
#endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_H_