core/systems/HandleSys.h
author David Anderson <dvander@alliedmods.net>
Wed Aug 01 02:12:47 2007 +0000 (2007-08-01)
changeset 1231 17badaf66ce4
parent 900 b38c83f9d526
child 1330 ab94316bb52b
permissions -rw-r--r--
updated more header files (mostly internal now)
dvander@370
     1
/**
ds@653
     2
 * vim: set ts=4 :
dvander@1231
     3
 * ================================================================
dvander@1231
     4
 * SourceMod
dvander@1231
     5
 * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
dvander@1231
     6
 * ================================================================
dvander@370
     7
 *
dvander@1231
     8
 * This program is free software; you can redistribute it and/or 
dvander@1231
     9
 * modify it under the terms of the GNU General Public License, 
dvander@1231
    10
 * version 3.0, as published by the Free Software Foundation.
dvander@1231
    11
 * 
dvander@1231
    12
 * This program is distributed in the hope that it will be useful,
dvander@1231
    13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
dvander@1231
    14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
dvander@1231
    15
 * GNU General Public License for more details.
dvander@1231
    16
 *
dvander@1231
    17
 * You should have received a copy of the GNU General Public License
dvander@1231
    18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
dvander@1231
    20
 * As a special exception, AlliedModders LLC gives you permission to 
dvander@1231
    21
 * link the code of this program (as well as its derivative works) to 
dvander@1231
    22
 * "Half-Life 2," the "Source Engine," the "SourcePawn JIT," and any 
dvander@1231
    23
 * Game MODs that run on software by the Valve Corporation.  You must 
dvander@1231
    24
 * obey the GNU General Public License in all respects for all other 
dvander@1231
    25
 * code used. Additionally, AlliedModders LLC grants this exception 
dvander@1231
    26
 * to all derivative works. AlliedModders LLC defines further 
dvander@1231
    27
 * exceptions, found in LICENSE.txt (as of this writing, version 
dvander@1231
    28
 * JULY-31-2007), or <http://www.sourcemod.net/license.php>.
dvander@370
    29
 *
dvander@370
    30
 * Version: $Id$
dvander@370
    31
 */
dvander@370
    32
dvander@218
    33
#ifndef _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
dvander@218
    34
#define _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
dvander@218
    35
dvander@218
    36
#include <IHandleSys.h>
dvander@900
    37
#include <stdio.h>
dvander@218
    38
#include "sm_globals.h"
dvander@218
    39
#include "sm_trie.h"
dvander@218
    40
#include "sourcemod.h"
dvander@218
    41
#include "sm_memtable.h"
dvander@218
    42
dvander@222
    43
#define HANDLESYS_MAX_HANDLES		(1<<14)
dvander@218
    44
#define HANDLESYS_MAX_TYPES			(1<<9)
dvander@218
    45
#define HANDLESYS_MAX_SUBTYPES		0xF
dvander@218
    46
#define HANDLESYS_SUBTYPE_MASK		0xF
dvander@218
    47
#define HANDLESYS_TYPEARRAY_SIZE	(HANDLESYS_MAX_TYPES * (HANDLESYS_MAX_SUBTYPES + 1))
dvander@218
    48
#define HANDLESYS_MAX_SERIALS		0xFFFF
dvander@218
    49
#define HANDLESYS_SERIAL_MASK		0xFFFF0000
dvander@218
    50
#define HANDLESYS_HANDLE_MASK		0x0000FFFF
dvander@218
    51
dvander@229
    52
/**
dvander@229
    53
 *   The QHandle is a nasty structure that compacts the handle system into a big vector.
dvander@229
    54
 * The members of the vector each encapsulate one Handle, however, they also act as nodes
dvander@229
    55
 * in an inlined linked list and an inlined vector.
dvander@229
    56
 *
dvander@229
    57
 *   The first of these lists is the 'freeID' list.  Each node from 1 to N (where N
dvander@229
    58
 * is the number of free nodes) has a 'freeID' that specifies a free Handle ID.  This
dvander@229
    59
 * is a quick hack to get around allocating a second base vector.
dvander@229
    60
 *
dvander@229
    61
 *   The second vector is the identity linked list.  An identity has its own handle, so
dvander@229
    62
 * these handles are used as sentinel nodes for index linking.  They point to the first and last
ds@487
    63
 * index into the handle array.  Each subsequent Handle who is owned by that identity is mapped into
dvander@229
    64
 * that list.  This lets owning identities be unloaded in O(n) time.
dvander@229
    65
 *
dvander@229
    66
 *   Eventually, there may be a third list for type chains.
dvander@229
    67
 */
dvander@229
    68
dvander@229
    69
enum HandleSet
dvander@229
    70
{
dvander@229
    71
	HandleSet_None = 0,
dvander@259
    72
	HandleSet_Used,			/* The Handle is in use */
dvander@259
    73
	HandleSet_Freed,		/* The "master" Handle of a clone chain is freed */
dvander@259
    74
	HandleSet_Identity,		/* The Handle is a special identity */
dvander@229
    75
};
dvander@229
    76
dvander@218
    77
struct QHandle
dvander@218
    78
{
dvander@222
    79
	HandleType_t type;			/* Handle type */
dvander@222
    80
	void *object;				/* Unmaintained object pointer */
dvander@229
    81
	IdentityToken_t *owner;		/* Identity of object which owns this */
dvander@222
    82
	unsigned int serial;		/* Serial no. for sanity checking */
dvander@222
    83
	unsigned int refcount;		/* Reference count for safe destruction */
dvander@262
    84
	unsigned int clone;			/* If non-zero, this is our cloned parent index */
dvander@229
    85
	HandleSet set;				/* Information about the handle's state */
dvander@528
    86
	bool access_special;		/* Whether or not access rules are special or type-derived */
dvander@789
    87
	bool is_destroying;			/* Whether or not the handle is being destroyed */
dvander@528
    88
	HandleAccess sec;			/* Security rules */
dvander@229
    89
	/* The following variables are unrelated to the Handle array, and used 
dvander@229
    90
	 * as an inlined chain of information */
dvander@229
    91
	unsigned int freeID;		/* ID of a free handle in the free handle chain */
dvander@229
    92
	/* Indexes into the handle array for owner membership.
dvander@229
    93
	 * For identity roots, these are treated as the head/tail. */
dvander@283
    94
	unsigned int ch_prev;		/* chained previous handle */
dvander@283
    95
	unsigned int ch_next;		/* chained next handle */
dvander@218
    96
};
dvander@218
    97
dvander@218
    98
struct QHandleType
dvander@218
    99
{
dvander@218
   100
	IHandleTypeDispatch *dispatch;
dvander@218
   101
	unsigned int freeID;
dvander@218
   102
	unsigned int children;
dvander@262
   103
	TypeAccess typeSec;
dvander@262
   104
	HandleAccess hndlSec;
dvander@218
   105
	unsigned int opened;
dvander@218
   106
	int nameIdx;
dvander@218
   107
};
dvander@218
   108
dvander@218
   109
class HandleSystem : 
dvander@218
   110
	public IHandleSys
dvander@218
   111
{
dvander@229
   112
	friend HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index);
dvander@229
   113
	friend class ShareSystem;
dvander@218
   114
public:
dvander@218
   115
	HandleSystem();
dvander@218
   116
	~HandleSystem();
dvander@218
   117
public: //IHandleSystem
dvander@262
   118
dvander@262
   119
	HandleType_t CreateType(const char *name,
dvander@262
   120
		IHandleTypeDispatch *dispatch,
dvander@262
   121
		HandleType_t parent,
dvander@262
   122
		const TypeAccess *typeAccess,
dvander@262
   123
		const HandleAccess *hndlAccess,
dvander@262
   124
		IdentityToken_t *ident,
dvander@262
   125
		HandleError *err);
dvander@262
   126
dvander@229
   127
	bool RemoveType(HandleType_t type, IdentityToken_t *ident);
dvander@262
   128
dvander@218
   129
	bool FindHandleType(const char *name, HandleType_t *type);
dvander@262
   130
dvander@218
   131
	Handle_t CreateHandle(HandleType_t type, 
dvander@262
   132
		void *object,
dvander@262
   133
		IdentityToken_t *owner,
dvander@262
   134
		IdentityToken_t *ident,
dvander@262
   135
		HandleError *err);
dvander@283
   136
dvander@262
   137
	HandleError FreeHandle(Handle_t handle, const HandleSecurity *pSecurity);
dvander@262
   138
dvander@262
   139
	HandleError CloneHandle(Handle_t handle, 
dvander@262
   140
		Handle_t *newhandle, 
dvander@262
   141
		IdentityToken_t *newOwner,
dvander@262
   142
		const HandleSecurity *pSecurity);
dvander@262
   143
dvander@262
   144
	HandleError ReadHandle(Handle_t handle, 
dvander@262
   145
		HandleType_t type, 
dvander@262
   146
		const HandleSecurity *pSecurity,
dvander@262
   147
		void **object);
dvander@262
   148
dvander@262
   149
	bool InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess);
dvander@262
   150
dvander@229
   151
	bool TypeCheck(HandleType_t intype, HandleType_t outtype);
dvander@528
   152
dvander@528
   153
	virtual Handle_t CreateHandleEx(HandleType_t type, 
dvander@528
   154
		void *object,
dvander@528
   155
		const HandleSecurity *pSec,
dvander@528
   156
		const HandleAccess *pAccess,
dvander@528
   157
		HandleError *err);
dvander@900
   158
dvander@900
   159
	void Dump(FILE *fp);
dvander@229
   160
protected:
dvander@222
   161
	/**
dvander@222
   162
	 * Decodes a handle with sanity and security checking.
dvander@222
   163
	 */
dvander@222
   164
	HandleError GetHandle(Handle_t handle, 
dvander@229
   165
						  IdentityToken_t *ident, 
dvander@222
   166
						  QHandle **pHandle, 
dvander@222
   167
						  unsigned int *index,
dvander@259
   168
						  bool ignoreFree=false);
dvander@222
   169
dvander@222
   170
	/**
dvander@222
   171
	 * Creates a basic handle and sets its reference count to 1.
dvander@222
   172
	 * Does not do any type or security checking.
dvander@222
   173
	 */
dvander@229
   174
	HandleError MakePrimHandle(HandleType_t type, 
dvander@229
   175
							   QHandle **pHandle, 
dvander@229
   176
							   unsigned int *index, 
dvander@229
   177
							   HandleType_t *handle,
dvander@283
   178
							   IdentityToken_t *owner,
dvander@283
   179
							   bool identity=false);
dvander@222
   180
dvander@222
   181
	/**
ds@729
   182
	 * Frees a primitive handle.  Does no object freeing, only reference count, bookkeeping, 
dvander@229
   183
	 * and linked list maintenance.
dvander@283
   184
	 * If used on an Identity handle, destroys all Handles under that identity.
dvander@222
   185
	 */
dvander@222
   186
	void ReleasePrimHandle(unsigned int index);
dvander@229
   187
dvander@229
   188
	/**
dvander@283
   189
	 * Sets the security owner of a type.
dvander@229
   190
	 */
dvander@229
   191
	void SetTypeSecurityOwner(HandleType_t type, IdentityToken_t *pToken);
dvander@229
   192
dvander@283
   193
	/**
dvander@283
   194
	 * Helper function to check access rights.
dvander@229
   195
	 */
dvander@283
   196
	bool CheckAccess(QHandle *pHandle, HandleAccessRight right, const HandleSecurity *pSecurity);
dvander@262
   197
dvander@283
   198
	/** 
dvander@283
   199
	 * Some wrappers for internal functions, so we can pass indexes instead of encoded handles.
dvander@283
   200
	 */
dvander@283
   201
	HandleError FreeHandle(QHandle *pHandle, unsigned int index);
dvander@283
   202
	void UnlinkHandleFromOwner(QHandle *pHandle, unsigned int index);
dvander@283
   203
	HandleError CloneHandle(QHandle *pHandle, unsigned int index, Handle_t *newhandle, IdentityToken_t *newOwner);
dvander@528
   204
	Handle_t CreateHandleInt(HandleType_t type, void *object, const HandleSecurity *pSec, HandleError *err, const HandleAccess *pAccess, bool identity);
dvander@222
   205
private:
dvander@218
   206
	QHandle *m_Handles;
dvander@218
   207
	QHandleType *m_Types;
dvander@218
   208
	Trie *m_TypeLookup;
dvander@218
   209
	unsigned int m_TypeTail;
dvander@218
   210
	unsigned int m_FreeTypes;
dvander@218
   211
	unsigned int m_HandleTail;
dvander@218
   212
	unsigned int m_FreeHandles;
dvander@218
   213
	unsigned int m_HSerial;
dvander@218
   214
	BaseStringTable *m_strtab;
dvander@218
   215
};
dvander@218
   216
dvander@218
   217
extern HandleSystem g_HandleSys;
dvander@218
   218
dvander@218
   219
#endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_H_