diff -r e28a9247061f -r 9ac720a36ce4 core/HandleSys.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core/HandleSys.h Wed Nov 19 02:16:45 2008 -0600
@@ -0,0 +1,225 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod
+ * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or .
+ *
+ * Version: $Id$
+ */
+
+#ifndef _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
+#define _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
+
+#include
+#include
+#include "sm_globals.h"
+#include "sm_trie.h"
+#include "sourcemod.h"
+#include "sm_memtable.h"
+
+#define HANDLESYS_MAX_HANDLES (1<<14)
+#define HANDLESYS_MAX_TYPES (1<<9)
+#define HANDLESYS_MAX_SUBTYPES 0xF
+#define HANDLESYS_SUBTYPE_MASK 0xF
+#define HANDLESYS_TYPEARRAY_SIZE (HANDLESYS_MAX_TYPES * (HANDLESYS_MAX_SUBTYPES + 1))
+#define HANDLESYS_MAX_SERIALS 0xFFFF
+#define HANDLESYS_SERIAL_MASK 0xFFFF0000
+#define HANDLESYS_HANDLE_MASK 0x0000FFFF
+
+#define HANDLESYS_MEMUSAGE_MIN_VERSION 3
+
+/**
+ * The QHandle is a nasty structure that compacts the handle system into a big vector.
+ * The members of the vector each encapsulate one Handle, however, they also act as nodes
+ * in an inlined linked list and an inlined vector.
+ *
+ * The first of these lists is the 'freeID' list. Each node from 1 to N (where N
+ * is the number of free nodes) has a 'freeID' that specifies a free Handle ID. This
+ * is a quick hack to get around allocating a second base vector.
+ *
+ * The second vector is the identity linked list. An identity has its own handle, so
+ * these handles are used as sentinel nodes for index linking. They point to the first and last
+ * index into the handle array. Each subsequent Handle who is owned by that identity is mapped into
+ * that list. This lets owning identities be unloaded in O(n) time.
+ *
+ * Eventually, there may be a third list for type chains.
+ */
+
+enum HandleSet
+{
+ HandleSet_None = 0,
+ HandleSet_Used, /* The Handle is in use */
+ HandleSet_Freed, /* The "master" Handle of a clone chain is freed */
+ HandleSet_Identity, /* The Handle is a special identity */
+};
+
+struct QHandle
+{
+ HandleType_t type; /* Handle type */
+ void *object; /* Unmaintained object pointer */
+ IdentityToken_t *owner; /* Identity of object which owns this */
+ unsigned int serial; /* Serial no. for sanity checking */
+ unsigned int refcount; /* Reference count for safe destruction */
+ unsigned int clone; /* If non-zero, this is our cloned parent index */
+ HandleSet set; /* Information about the handle's state */
+ bool access_special; /* Whether or not access rules are special or type-derived */
+ bool is_destroying; /* Whether or not the handle is being destroyed */
+ HandleAccess sec; /* Security rules */
+ /* The following variables are unrelated to the Handle array, and used
+ * as an inlined chain of information */
+ unsigned int freeID; /* ID of a free handle in the free handle chain */
+ /* Indexes into the handle array for owner membership.
+ * For identity roots, these are treated as the head/tail. */
+ unsigned int ch_prev; /* chained previous handle */
+ unsigned int ch_next; /* chained next handle */
+};
+
+struct QHandleType
+{
+ IHandleTypeDispatch *dispatch;
+ unsigned int freeID;
+ unsigned int children;
+ TypeAccess typeSec;
+ HandleAccess hndlSec;
+ unsigned int opened;
+ int nameIdx;
+};
+
+typedef void (HANDLE_REPORTER)(const char *str, ...);
+
+class HandleSystem :
+ public IHandleSys
+{
+ friend HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index);
+ friend class ShareSystem;
+public:
+ HandleSystem();
+ ~HandleSystem();
+public: //IHandleSystem
+
+ HandleType_t CreateType(const char *name,
+ IHandleTypeDispatch *dispatch,
+ HandleType_t parent,
+ const TypeAccess *typeAccess,
+ const HandleAccess *hndlAccess,
+ IdentityToken_t *ident,
+ HandleError *err);
+
+ bool RemoveType(HandleType_t type, IdentityToken_t *ident);
+
+ bool FindHandleType(const char *name, HandleType_t *type);
+
+ Handle_t CreateHandle(HandleType_t type,
+ void *object,
+ IdentityToken_t *owner,
+ IdentityToken_t *ident,
+ HandleError *err);
+
+ HandleError FreeHandle(Handle_t handle, const HandleSecurity *pSecurity);
+
+ HandleError CloneHandle(Handle_t handle,
+ Handle_t *newhandle,
+ IdentityToken_t *newOwner,
+ const HandleSecurity *pSecurity);
+
+ HandleError ReadHandle(Handle_t handle,
+ HandleType_t type,
+ const HandleSecurity *pSecurity,
+ void **object);
+
+ bool InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess);
+
+ bool TypeCheck(HandleType_t intype, HandleType_t outtype);
+
+ virtual Handle_t CreateHandleEx(HandleType_t type,
+ void *object,
+ const HandleSecurity *pSec,
+ const HandleAccess *pAccess,
+ HandleError *err);
+
+ void Dump(HANDLE_REPORTER rep);
+protected:
+ /**
+ * Decodes a handle with sanity and security checking.
+ */
+ HandleError GetHandle(Handle_t handle,
+ IdentityToken_t *ident,
+ QHandle **pHandle,
+ unsigned int *index,
+ bool ignoreFree=false);
+
+ /**
+ * Creates a basic handle and sets its reference count to 1.
+ * Does not do any type or security checking.
+ */
+ HandleError MakePrimHandle(HandleType_t type,
+ QHandle **pHandle,
+ unsigned int *index,
+ HandleType_t *handle,
+ IdentityToken_t *owner,
+ bool identity=false);
+
+ /**
+ * Frees a primitive handle. Does no object freeing, only reference count, bookkeeping,
+ * and linked list maintenance.
+ * If used on an Identity handle, destroys all Handles under that identity.
+ */
+ void ReleasePrimHandle(unsigned int index);
+
+ /**
+ * Sets the security owner of a type.
+ */
+ void SetTypeSecurityOwner(HandleType_t type, IdentityToken_t *pToken);
+
+ /**
+ * Helper function to check access rights.
+ */
+ bool CheckAccess(QHandle *pHandle, HandleAccessRight right, const HandleSecurity *pSecurity);
+
+ /**
+ * Some wrappers for internal functions, so we can pass indexes instead of encoded handles.
+ */
+ HandleError FreeHandle(QHandle *pHandle, unsigned int index);
+ void UnlinkHandleFromOwner(QHandle *pHandle, unsigned int index);
+ HandleError CloneHandle(QHandle *pHandle, unsigned int index, Handle_t *newhandle, IdentityToken_t *newOwner);
+ Handle_t CreateHandleInt(HandleType_t type, void *object, const HandleSecurity *pSec, HandleError *err, const HandleAccess *pAccess, bool identity);
+
+ bool TryAndFreeSomeHandles();
+ HandleError TryAllocHandle(unsigned int *handle);
+private:
+ QHandle *m_Handles;
+ QHandleType *m_Types;
+ Trie *m_TypeLookup;
+ unsigned int m_TypeTail;
+ unsigned int m_FreeTypes;
+ unsigned int m_HandleTail;
+ unsigned int m_FreeHandles;
+ unsigned int m_HSerial;
+ BaseStringTable *m_strtab;
+};
+
+extern HandleSystem g_HandleSys;
+
+#endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_H_