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