void HandleSystem::ReleasePrimHandle(unsigned int index) { QHandle *pHandle = &m_Handles[index]; HandleSet set = pHandle->set; if (pHandle->owner && (set != HandleSet_Identity)) { UnlinkHandleFromOwner(pHandle, index); } /* Were we an identity ourself? */ QHandle *pLocal; if (set == HandleSet_Identity) { /* Extra work to do. We need to find everything connected to this identity and release it. */ unsigned int ch_index; #if defined _DEBUG unsigned int old_index = 0; #endif while ((ch_index = pHandle->ch_next) != 0) { pLocal = &m_Handles[ch_index]; #if defined _DEBUG assert(old_index != ch_index); assert(pLocal->set == HandleSet_Used); old_index = ch_index; #endif FreeHandle(pLocal, ch_index); } } pHandle->set = HandleSet_None; m_Types[pHandle->type].opened--; m_Handles[++m_FreeHandles].freeID = index; }
HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index) { QHandleType *pType = &m_Types[pHandle->type]; if (pHandle->clone) { /* If we're a clone, decrease the parent reference count */ QHandle *pMaster; unsigned int master; /* Note that if we ever have per-handle security, we would need to re-check * the access on this Handle. */ master = pHandle->clone; pMaster = &m_Handles[master]; /* Release the clone now */ ReleasePrimHandle(index); /* Decrement the master's reference count */ if (--pMaster->refcount == 0) { /* Type should be the same but do this anyway... */ pType = &m_Types[pMaster->type]; pMaster->is_destroying = true; pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object); ReleasePrimHandle(master); } } else if (pHandle->set == HandleSet_Identity) { /* If we're an identity, skip all this stuff! * NOTE: SHARESYS DOES NOT CARE ABOUT THE DESTRUCTOR */ ReleasePrimHandle(index); } else { /* Decrement, free if necessary */ if (--pHandle->refcount == 0) { pHandle->is_destroying = true; pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object); ReleasePrimHandle(index); } else { /* We must be cloned, so mark ourselves as freed */ pHandle->set = HandleSet_Freed; /* Now, unlink us, so we're not being tracked by the owner */ if (pHandle->owner) { UnlinkHandleFromOwner(pHandle, index); } } } return HandleError_None; }