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