Partial fix

--HG--
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40122
This commit is contained in:
Pavol Marko 2005-10-05 21:51:02 +00:00
parent 047c7e0c99
commit 36dda69d9d
3 changed files with 97 additions and 8 deletions

View File

@ -341,12 +341,26 @@ namespace SourceHook
bool erase; bool erase;
for (List<HookInfo>::iterator hookiter = hooks.begin(); for (List<HookInfo>::iterator hookiter = hooks.begin();
hookiter != hooks.end(); erase ? hookiter = hooks.erase(hookiter) : ++hookiter) hookiter != hooks.end(); )
{ {
erase = hookiter->plug == plug && hookiter->handler->IsEqual(handler) && erase = hookiter->plug == plug && hookiter->handler->IsEqual(handler) &&
hookiter->thisptr_offs == thisptr_offs; hookiter->thisptr_offs == thisptr_offs;
if (erase) if (erase)
{
hookiter->handler->DeleteThis(); // Make the _plugin_ delete the handler object hookiter->handler->DeleteThis(); // Make the _plugin_ delete the handler object
// Move all iterators pointing at this
List<HookInfo>::iterator oldhookiter = hookiter;
hookiter = hooks.erase(hookiter);
List<HookInfo>::iterator newhookiter = hookiter;
--newhookiter; // The hook loop will ++ it then
CHookList::CIter *pItIter;
for (pItIter = iface_iter->m_PreHooks.m_UsedIters; pItIter; pItIter = pItIter->m_pNext)
if (pItIter->m_Iter == oldhookiter)
pItIter->m_Iter = newhookiter;
}
else
++hookiter;
} }
if (iface_iter->m_PostHooks.m_List.empty() && iface_iter->m_PreHooks.m_List.empty()) if (iface_iter->m_PostHooks.m_List.empty() && iface_iter->m_PreHooks.m_List.empty())
{ {
@ -701,10 +715,10 @@ namespace SourceHook
// CHookList // CHookList
//////////////////////////// ////////////////////////////
CSourceHookImpl::CHookList::CHookList() : m_FreeIters(NULL) CSourceHookImpl::CHookList::CHookList() : m_FreeIters(NULL), m_UsedIters(NULL)
{ {
} }
CSourceHookImpl::CHookList::CHookList(const CHookList &other) : m_List(other.m_List), m_FreeIters(NULL) CSourceHookImpl::CHookList::CHookList(const CHookList &other) : m_List(other.m_List), m_FreeIters(NULL), m_UsedIters(NULL)
{ {
} }
CSourceHookImpl::CHookList::~CHookList() CSourceHookImpl::CHookList::~CHookList()
@ -718,19 +732,41 @@ namespace SourceHook
} }
IHookList::IIter *CSourceHookImpl::CHookList::GetIter() IHookList::IIter *CSourceHookImpl::CHookList::GetIter()
{ {
CIter *ret;
if (m_FreeIters) if (m_FreeIters)
{ {
CIter *ret = m_FreeIters; ret = m_FreeIters;
m_FreeIters = ret->m_pNext; m_FreeIters = ret->m_pNext;
ret->GoToBegin(); ret->GoToBegin();
return ret;
} }
return new CIter(this); else
{
ret = new CIter(this);
}
ret->m_pNext = m_UsedIters;
ret->m_pPrev = NULL;
if (m_UsedIters)
m_UsedIters->m_pPrev = ret;
m_UsedIters = ret;
return ret;
} }
void CSourceHookImpl::CHookList::ReleaseIter(IIter *pIter) void CSourceHookImpl::CHookList::ReleaseIter(IIter *pIter)
{ {
CIter *pIter2 = static_cast<CIter*>(pIter); CIter *pIter2 = static_cast<CIter*>(pIter);
// Unlink from m_UsedIters
if (pIter2->m_pNext)
pIter2->m_pNext->m_pPrev = pIter2->m_pPrev;
if (pIter2->m_pPrev)
pIter2->m_pPrev->m_pNext = pIter2->m_pNext;
// Link to m_FreeIters
pIter2->m_pNext = m_FreeIters; pIter2->m_pNext = m_FreeIters;
m_FreeIters = pIter2; m_FreeIters = pIter2;
} }
@ -750,13 +786,21 @@ namespace SourceHook
bool CSourceHookImpl::CHookList::CIter::End() bool CSourceHookImpl::CHookList::CIter::End()
{ {
if (!m_pList)
return false;
return m_Iter == m_pList->m_List.end(); return m_Iter == m_pList->m_List.end();
} }
void CSourceHookImpl::CHookList::CIter::Next() void CSourceHookImpl::CHookList::CIter::Next()
{ {
if (!m_pList)
return;
++m_Iter; ++m_Iter;
SkipPaused(); SkipPaused();
} }
void CSourceHookImpl::CHookList::CIter::Clear()
{
m_pList = NULL;
}
void CSourceHookImpl::CHookList::CIter::SkipPaused() void CSourceHookImpl::CHookList::CIter::SkipPaused()
{ {
while (m_Iter != m_pList->m_List.end() && m_Iter->paused) while (m_Iter != m_pList->m_List.end() && m_Iter->paused)

View File

@ -68,10 +68,12 @@ namespace SourceHook
friend class CHookList; friend class CHookList;
CHookList *m_pList; CHookList *m_pList;
List<HookInfo>::iterator m_Iter;
void SkipPaused(); void SkipPaused();
public: public:
List<HookInfo>::iterator m_Iter;
CIter(CHookList *pList); CIter(CHookList *pList);
virtual ~CIter(); virtual ~CIter();
@ -83,10 +85,14 @@ namespace SourceHook
ISHDelegate *Handler(); ISHDelegate *Handler();
int ThisPtrOffs(); int ThisPtrOffs();
CIter *m_pNext; // When stored in m_FreeIters void Clear();
CIter *m_pNext; // When stored in m_FreeIters and m_UsedIters
CIter *m_pPrev; // Only used when stored in m_UsedIters
}; };
CIter *m_FreeIters; CIter *m_FreeIters;
CIter *m_UsedIters;
CHookList(); CHookList();
CHookList(const CHookList &other); CHookList(const CHookList &other);

View File

@ -5,6 +5,28 @@
void *___testbail_gabgab; void *___testbail_gabgab;
namespace
{
class zomg_lolz
{
public:
virtual void zomg()
{
}
};
SH_DECL_HOOK0_void(zomg_lolz, zomg, SH_NOATTRIB, 0);
void Handler()
{
printf("H1\n");
SH_REMOVE_HOOK_STATICFUNC(zomg_lolz, zomg, reinterpret_cast<zomg_lolz*>(META_IFACEPTR),
Handler, false);
}
void Handler2()
{
printf("H2\n");
}
}
bool TestBail(std::string &error) bool TestBail(std::string &error)
{ {
SourceHook::CSourceHookImpl g_SHImpl; SourceHook::CSourceHookImpl g_SHImpl;
@ -32,6 +54,23 @@ bool TestBail(std::string &error)
// If it didn't crash, it's ok // If it didn't crash, it's ok
// NEW TEST: Remove hook from handler
zomg_lolz inst;
SH_ADD_HOOK_STATICFUNC(zomg_lolz, zomg, &inst, Handler, false);
SH_ADD_HOOK_STATICFUNC(zomg_lolz, zomg, &inst, Handler2, false);
zomg_lolz *mwah = &inst;
mwah->zomg();
mwah->zomg();
SH_ADD_HOOK_STATICFUNC(zomg_lolz, zomg, &inst, Handler, false);
SH_REMOVE_HOOK_STATICFUNC(zomg_lolz, zomg, &inst, Handler2, false);
mwah->zomg();
mwah->zomg();
// Shouldn't crash again...
return true; return true;
} }