diff options
Diffstat (limited to 'Src/replicant/Wasabi/SysCallbacks.cpp')
-rw-r--r-- | Src/replicant/Wasabi/SysCallbacks.cpp | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/Src/replicant/Wasabi/SysCallbacks.cpp b/Src/replicant/Wasabi/SysCallbacks.cpp new file mode 100644 index 00000000..c77eaafd --- /dev/null +++ b/Src/replicant/Wasabi/SysCallbacks.cpp @@ -0,0 +1,98 @@ +#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; +} |