aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/Wasabi/SysCallbacks.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/replicant/Wasabi/SysCallbacks.cpp')
-rw-r--r--Src/replicant/Wasabi/SysCallbacks.cpp98
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;
+}