| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 | /** (c) Nullsoft, Inc.         C O N F I D E N T I A L** Filename: ** Project:** Description:** Author: Ben Allison [email protected]** Created:**/#include "main.h"#include "SysCallbacks.h"#include <api/syscb/callbacks/syscb.h>#include "../nu/AutoLock.h"using namespace Nullsoft::Utility;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 corruptionint SysCallbacks::syscb_registerCallback(SysCallback *cb, void *param){	AutoLock lock(callbackGuard LOCKNAME("SysCallbacks::syscb_registerCallback"));	int event_type = cb->getEventType();	//CallbackList *&callbacks = callback_map[event_type];	//if (!callbacks)	//	callbacks = new CallbackList;	//callbacks->push_back(cb); 	EventMap::iterator find = callback_map.find(event_type);	CallbackList* callbacks = 0;	if (find != callback_map.end())	{		callbacks = find->second;	}	else	{		callbacks = new CallbackList();		callback_map.insert({ event_type, callbacks });	}	if (callbacks)	{		callbacks->push_back(cb);	}	return 1;}int SysCallbacks::syscb_deregisterCallback(SysCallback *cb){	AutoLock lock(callbackGuard LOCKNAME("SysCallbacks::syscb_deregisterCallback"));	if (inCallback)		deleteMeAfterCallbacks.push_back(cb);	else	{		int event_type = cb->getEventType();		EventMap::iterator find = callback_map.find(event_type);		if (find != callback_map.end())		{			CallbackList *callbacks = find->second;			if (callbacks)			{				//callbacks->eraseAll(cb);				auto it = callbacks->begin();				while ( it != callbacks->end())				{					if (*it != cb)					{						it++;						continue;					}					it = callbacks->erase(it);				}			}		}	}	return 1;}int SysCallbacks::syscb_issueCallback(int event_type, int msg, intptr_t param1 , intptr_t param2){	AutoLock lock(callbackGuard LOCKNAME("SysCallbacks::syscb_issueCallback"));	reentry++;	inCallback=true;	EventMap::iterator find = callback_map.find(event_type);	if (find != callback_map.end())	{		CallbackList *callbacks = find->second;		if (callbacks)		{			for (size_t i=0;i<callbacks->size();i++)			{				SysCallback *callback = callbacks->at(i);				//if (!deleteMeAfterCallbacks.contains(callback))				//	callback->notify(msg, param1, param2);				bool found = false;				for (auto obj : deleteMeAfterCallbacks)				{					if (obj == callback)					{						found = true;						break;					}				}				if (!found)					callback->notify(msg, param1, param2);			}		}	}	inCallback=false;	reentry--;	if (reentry==0)	{		for ( SysCallback *l_sys_call_back : deleteMeAfterCallbacks )		{			for (EventMap::iterator itr=callback_map.begin(); itr != callback_map.end(); itr++)			{				CallbackList *callbacks = itr->second;				if (callbacks)				{					//callbacks->eraseAll(cb);					auto it = callbacks->begin();					while (it != callbacks->end())					{						if (*it != l_sys_call_back )						{							it++;							continue;						}						it = callbacks->erase(it);					}				}			}		}		deleteMeAfterCallbacks.clear();	}	return 1;}SysCallback *SysCallbacks::syscb_enum(int event_type, size_t n){	AutoLock lock(callbackGuard LOCKNAME("SysCallbacks::syscb_enum"));	// TODO: maybe check !deleteMeAfterCallbacks.contains(callbacks[i])	if (event_type)	{		EventMap::iterator find = callback_map.find(event_type);		if (find != callback_map.end())		{			CallbackList *callbacks = find->second;			if (callbacks)			{				if (n <= callbacks->size())				{					SysCallback *callback = callbacks->at(n);					if (callback)						callback->AddRef(); 	// benski> don't be fooled.  most objects don't actually support reference counting					return callback;				}			}		}	}	else	{		// enumerates ALL syscallbacks		for (EventMap::iterator itr=callback_map.begin(); itr != callback_map.end(); itr++)		{			CallbackList *callbacks = itr->second;			if (callbacks)			{				if (n >= callbacks->size())				{					n-=callbacks->size();				}				else				{					SysCallback *callback = callbacks->at(n);					if (callback)						callback->AddRef(); 	// benski> don't be fooled.  most objects don't actually support reference counting					return callback;				}			}		}	}	return 0;}#define CBCLASS SysCallbacksSTART_DISPATCH;CB(API_SYSCB_SYSCB_REGISTERCALLBACK, syscb_registerCallback)CB(API_SYSCB_SYSCB_DEREGISTERCALLBACK, syscb_deregisterCallback)CB(API_SYSCB_SYSCB_ISSUECALLBACK, syscb_issueCallback)CB(API_SYSCB_SYSCB_ENUM, syscb_enum)END_DISPATCH;#undef CBCLASS
 |