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