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