2 * ===============================================================
3 * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
4 * ===============================================================
6 * This file is not open source and may not be copied without explicit
7 * written permission of AlliedModders LLC. This file may not be redistributed
8 * in whole or significant part.
9 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
14 #ifndef _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
15 #define _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
17 #include <IHandleSys.h>
18 #include "sm_globals.h"
20 #include "sourcemod.h"
21 #include "sm_memtable.h"
23 #define HANDLESYS_MAX_HANDLES (1<<14)
24 #define HANDLESYS_MAX_TYPES (1<<9)
25 #define HANDLESYS_MAX_SUBTYPES 0xF
26 #define HANDLESYS_SUBTYPE_MASK 0xF
27 #define HANDLESYS_TYPEARRAY_SIZE (HANDLESYS_MAX_TYPES * (HANDLESYS_MAX_SUBTYPES + 1))
28 #define HANDLESYS_MAX_SERIALS 0xFFFF
29 #define HANDLESYS_SERIAL_MASK 0xFFFF0000
30 #define HANDLESYS_HANDLE_MASK 0x0000FFFF
33 * The QHandle is a nasty structure that compacts the handle system into a big vector.
34 * The members of the vector each encapsulate one Handle, however, they also act as nodes
35 * in an inlined linked list and an inlined vector.
37 * The first of these lists is the 'freeID' list. Each node from 1 to N (where N
38 * is the number of free nodes) has a 'freeID' that specifies a free Handle ID. This
39 * is a quick hack to get around allocating a second base vector.
41 * The second vector is the identity linked list. An identity has its own handle, so
42 * these handles are used as sentinel nodes for index linking. They point to the first and last
43 * index into the handle array. Each subsequent Handle who is owned by that indentity is mapped into
44 * that list. This lets owning identities be unloaded in O(n) time.
46 * Eventually, there may be a third list for type chains.
52 HandleSet_Used, /* The Handle is in use */
53 HandleSet_Freed, /* The "master" Handle of a clone chain is freed */
54 HandleSet_Identity, /* The Handle is a special identity */
59 HandleType_t type; /* Handle type */
60 void *object; /* Unmaintained object pointer */
61 IdentityToken_t *owner; /* Identity of object which owns this */
62 unsigned int serial; /* Serial no. for sanity checking */
63 unsigned int refcount; /* Reference count for safe destruction */
64 unsigned int clone; /* If non-zero, this is our cloned parent index */
65 HandleSet set; /* Information about the handle's state */
66 /* The following variables are unrelated to the Handle array, and used
67 * as an inlined chain of information */
68 unsigned int freeID; /* ID of a free handle in the free handle chain */
69 /* Indexes into the handle array for owner membership.
70 * For identity roots, these are treated as the head/tail. */
71 unsigned int ch_prev; /* chained previous handle */
72 unsigned int ch_next; /* chained next handle */
77 IHandleTypeDispatch *dispatch;
79 unsigned int children;
89 friend HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index);
90 friend class ShareSystem;
94 public: //IHandleSystem
96 HandleType_t CreateType(const char *name,
97 IHandleTypeDispatch *dispatch,
99 const TypeAccess *typeAccess,
100 const HandleAccess *hndlAccess,
101 IdentityToken_t *ident,
104 bool RemoveType(HandleType_t type, IdentityToken_t *ident);
106 bool FindHandleType(const char *name, HandleType_t *type);
108 Handle_t CreateHandle(HandleType_t type,
110 IdentityToken_t *owner,
111 IdentityToken_t *ident,
114 HandleError FreeHandle(Handle_t handle, const HandleSecurity *pSecurity);
116 HandleError CloneHandle(Handle_t handle,
118 IdentityToken_t *newOwner,
119 const HandleSecurity *pSecurity);
121 HandleError ReadHandle(Handle_t handle,
123 const HandleSecurity *pSecurity,
126 bool InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess);
128 bool TypeCheck(HandleType_t intype, HandleType_t outtype);
131 * Decodes a handle with sanity and security checking.
133 HandleError GetHandle(Handle_t handle,
134 IdentityToken_t *ident,
137 bool ignoreFree=false);
140 * Creates a basic handle and sets its reference count to 1.
141 * Does not do any type or security checking.
143 HandleError MakePrimHandle(HandleType_t type,
146 HandleType_t *handle,
147 IdentityToken_t *owner,
148 bool identity=false);
151 * Frees a primitive handle. Does no object freeing, only reference count, bookkeepping,
152 * and linked list maintenance.
153 * If used on an Identity handle, destroys all Handles under that identity.
155 void ReleasePrimHandle(unsigned int index);
158 * Sets the security owner of a type.
160 void SetTypeSecurityOwner(HandleType_t type, IdentityToken_t *pToken);
163 * Helper function to check access rights.
165 bool CheckAccess(QHandle *pHandle, HandleAccessRight right, const HandleSecurity *pSecurity);
168 * Some wrappers for internal functions, so we can pass indexes instead of encoded handles.
170 HandleError FreeHandle(QHandle *pHandle, unsigned int index);
171 void UnlinkHandleFromOwner(QHandle *pHandle, unsigned int index);
172 HandleError CloneHandle(QHandle *pHandle, unsigned int index, Handle_t *newhandle, IdentityToken_t *newOwner);
173 Handle_t CreateHandleEx(HandleType_t type, void *object, IdentityToken_t *owner, IdentityToken_t *ident, HandleError *err, bool identity);
176 QHandleType *m_Types;
178 unsigned int m_TypeTail;
179 unsigned int m_FreeTypes;
180 unsigned int m_HandleTail;
181 unsigned int m_FreeHandles;
182 unsigned int m_HSerial;
183 BaseStringTable *m_strtab;
186 extern HandleSystem g_HandleSys;
188 #endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_H_