99 lines
2.4 KiB
C++
99 lines
2.4 KiB
C++
|
#include "SysCallbacks.h"
|
||
|
#include "syscb/ifc_syscallback.h"
|
||
|
|
||
|
using namespace nu;
|
||
|
|
||
|
SysCallbacks::SysCallbacks()
|
||
|
{
|
||
|
reentry=0;
|
||
|
inCallback=false;
|
||
|
}
|
||
|
|
||
|
//note: it's OK to add in the middle of an issueCallback
|
||
|
//because new callbacks go at the end of the list
|
||
|
//and the lockguard prevents list corruption
|
||
|
int SysCallbacks::SysCallbacks_RegisterCallback(ifc_sysCallback *cb)
|
||
|
{
|
||
|
AutoLock lock(callbackGuard LOCKNAME("SysCallbacks::syscb_registerCallback"));
|
||
|
callbacks.push_back(cb);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int SysCallbacks::SysCallbacks_UnregisterCallback(ifc_sysCallback *cb)
|
||
|
{
|
||
|
AutoLock lock(callbackGuard LOCKNAME("SysCallbacks::syscb_deregisterCallback"));
|
||
|
if (inCallback)
|
||
|
deleteMeAfterCallbacks.push_back(cb);
|
||
|
else
|
||
|
{
|
||
|
//callbacks.eraseAll(cb);
|
||
|
auto it = callbacks.begin();
|
||
|
while (it != callbacks.end())
|
||
|
{
|
||
|
if (*it != cb)
|
||
|
{
|
||
|
it++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
it = callbacks.erase(it);
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int SysCallbacks::SysCallbacks_IssueCallback( GUID eventtype, int msg, intptr_t param1, intptr_t param2 )
|
||
|
{
|
||
|
AutoLock lock( callbackGuard LOCKNAME( "SysCallbacks::syscb_issueCallback" ) );
|
||
|
reentry++;
|
||
|
inCallback = true;
|
||
|
|
||
|
for ( ifc_sysCallback *l_call_back : callbacks )
|
||
|
{
|
||
|
//if (!deleteMeAfterCallbacks.contains(callbacks[i]) && callbacks[i]->GetEventType() == eventtype)
|
||
|
if ( deleteMeAfterCallbacks.end() == std::find( deleteMeAfterCallbacks.begin(), deleteMeAfterCallbacks.end(), l_call_back ) && l_call_back->GetEventType() == eventtype )
|
||
|
l_call_back->Notify( msg, param1, param2 );
|
||
|
}
|
||
|
inCallback = false;
|
||
|
reentry--;
|
||
|
if ( reentry == 0 )
|
||
|
{
|
||
|
for ( ifc_sysCallback *l_delete_me_after_call_back : deleteMeAfterCallbacks )
|
||
|
{
|
||
|
//callbacks.eraseAll(deleteMeAfterCallbacks[i]);
|
||
|
auto it = callbacks.begin();
|
||
|
while ( it != callbacks.end() )
|
||
|
{
|
||
|
if ( *it != l_delete_me_after_call_back )
|
||
|
{
|
||
|
it++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
it = callbacks.erase( it );
|
||
|
}
|
||
|
}
|
||
|
deleteMeAfterCallbacks.clear();
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
ifc_sysCallback *SysCallbacks::SysCallbacks_Enum( GUID eventtype, size_t n )
|
||
|
{
|
||
|
AutoLock lock( callbackGuard LOCKNAME( "SysCallbacks::syscb_enum" ) );
|
||
|
// TODO: maybe check !deleteMeAfterCallbacks.contains(callbacks[i])
|
||
|
for ( ifc_sysCallback *callback : callbacks )
|
||
|
{
|
||
|
if ( callback->GetEventType() == eventtype )
|
||
|
{
|
||
|
if ( n-- == 0 )
|
||
|
{
|
||
|
// benski> don't be fooled. most objects don't actually support reference counting
|
||
|
callback->Retain();
|
||
|
return callback;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|