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