123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- /** (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 "ServiceManager.h"
- #include <api.h>
- #include <api/service/waservicefactory.h>
- #include "../nu/AutoLock.h"
- #include <api/syscb/callbacks/syscb.h>
- #include <api/syscb/callbacks/svccb.h>
- using namespace Nullsoft::Utility;
- struct Counter
- {
- Counter( waServiceFactory *_owner, void *_ptr ) : ptr( _ptr ), owner( _owner ) {}
- void *ptr;
- waServiceFactory *owner;
- };
- ServiceManager::ServiceManager() : serviceGuard(512)
- {}
- int ServiceManager::service_register( waServiceFactory *svc )
- {
- AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_register" ) );
- FOURCC service_type = svc->getServiceType();
- // add the service to the master list
- services.push_back( svc );
- // add it to the by-type lookup
- ServiceList *&type_list = services_by_type[ service_type ];
- if ( !type_list )
- type_list = new ServiceList;
- type_list->push_back( svc );
- // send notifications
- svc->serviceNotify( SvcNotify::ONREGISTERED );
- WASABI_API_SYSCB->syscb_issueCallback( SysCallback::SERVICE, SvcCallback::ONREGISTER, (intptr_t)service_type, reinterpret_cast<intptr_t>( svc ) );
- return 1;
- }
- int ServiceManager::service_deregister( waServiceFactory *svc )
- {
- AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_deregister" ) );
- FOURCC service_type = svc->getServiceType();
- // remove it from the master list
- //services.eraseObject(svc);
- auto it = std::find( services.begin(), services.end(), svc );
- if ( it != services.end() )
- services.erase( it );
- // and from the type lookup map
- ServiceList *type_list = services_by_type[ service_type ];
- if ( type_list )
- {
- //type_list->eraseObject(svc);
- auto it = std::find( type_list->begin(), type_list->end(), svc );
- if ( it != type_list->end() )
- type_list->erase( it );
- }
- WASABI_API_SYSCB->syscb_issueCallback( SysCallback::SERVICE, SvcCallback::ONDEREGISTER, (intptr_t)service_type, reinterpret_cast<intptr_t>( svc ) );
- svc->serviceNotify( SvcNotify::ONDEREGISTERED );
- return 1;
- }
- size_t ServiceManager::service_getNumServices( FOURCC svc_type )
- {
- AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_getNumServices" ) );
- if ( svc_type )
- {
- ServiceList *type_list = services_by_type[ svc_type ];
- if ( type_list )
- return type_list->size();
- else
- return 0;
- }
- else
- return services.size();
- }
- waServiceFactory *ServiceManager::service_enumService( FOURCC svc_type, size_t n )
- {
- AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_enumService" ) );
- ServiceList *type_list = 0;
- if ( svc_type )
- type_list = services_by_type[ svc_type ];
- else
- type_list = &services;
- if ( type_list && n < type_list->size() )
- return type_list->at( n );
- else
- return 0;
- }
- waServiceFactory *ServiceManager::service_getServiceByGuid( GUID guid )
- {
- AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_getServiceByGuid" ) );
- for ( waServiceFactory *l_service : services )
- {
- if ( l_service->getGuid() == guid )
- return l_service;
- }
- return NULL;
- }
- int ServiceManager::service_lock( waServiceFactory *owner, void *svcptr )
- {
- if ( owner == NULL || svcptr == NULL )
- return 0;
- AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_lock" ) );
- locks.push_back( new Counter( owner, svcptr ) );
- return 1;
- }
- int ServiceManager::service_clientLock( void *svcptr )
- {
- return 1;
- }
- int ServiceManager::service_release( void *svcptr )
- {
- AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_release" ) );
- for ( size_t i = 0; i != locks.size(); i++ )
- {
- if ( locks[ i ]->ptr == svcptr )
- {
- void *ptr = locks[ i ]->ptr;
- waServiceFactory *owner = locks[ i ]->owner;
- delete locks[ i ];
- locks.erase( locks.begin() + i );
- owner->releaseInterface( ptr );
- return 1;
- }
- }
- return 0;
- }
- const char *ServiceManager::service_getTypeName( FOURCC svc_type )
- {
- return NULL;
- }
- int ServiceManager::service_unlock( void *svcptr )
- {
- AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_unlock" ) );
- for ( size_t i = 0; i != locks.size(); i++ )
- {
- if ( locks[ i ]->ptr == svcptr )
- {
- delete locks[ i ];
- locks.erase( locks.begin() + i );
- return 1;
- }
- }
- return 0;
- }
- int ServiceManager::service_isvalid( FOURCC svctype, waServiceFactory *service )
- {
- AutoLock lock( serviceGuard LOCKNAME( "ServiceManager::service_isvalid" ) );
- //return !!services.contains(service);
- return ( services.end() != std::find( services.begin(), services.end(), service ) );
- }
- int ServiceManager::service_compactDuplicates( waServiceFactory *me )
- {
- // first, find 'me'
- GUID guid = me->getGuid();
- size_t me_index = 0;
- //bool found = services.findItem(me, &me_index);
- //if (!found)
- // return 1;
- if ( services.end() == std::find( services.begin(), services.end(), me ) )
- return 1;
- ServiceList *type_list = services_by_type[ me->getServiceType() ];
- // go in reverse order because service to compact is likely at the end
- size_t n = services.size();
- while ( n-- ) // n is guaranteed to be >0 because otherwise the 'find' loop above would have failed
- {
- waServiceFactory *n_service = services[ n ];
- if ( n != me_index && n_service != me && n_service->getGuid() == guid )
- {
- services[ me_index ] = n_service;
- services.erase( services.begin() + n );
- // fix up our by-type cache
- if ( type_list )
- {
- size_t me_index = 0;
- size_t n_index = 0;
- //----------------------------------------------------
- // Replaced with code below this commented code
- //if (type_list->findItem_reverse(n_service, &n_index) && type_list->findItem(me, &me_index))
- //{
- // type_list->at(me_index) = n_service;
- // type_list->eraseindex(n_index);
- //}
- bool foundService = false;
- for ( int idx = type_list->size() - 1; idx >= 0; idx-- )
- {
- if ( type_list->at( idx ) == n_service )
- {
- foundService = true;
- n_index = idx;
- break;
- }
- }
- bool foundMe = false;
- for ( int idx2 = 0; idx2 < type_list->size(); idx2++ )
- {
- if ( type_list->at( idx2 ) == me )
- {
- foundMe = true;
- me_index = idx2;
- break;
- }
- }
- if ( foundService && foundMe )
- {
- type_list->at( me_index ) = n_service;
- type_list->erase( type_list->begin() + n_index );
- }
- //--------------------------------------------------
- }
- me->serviceNotify( SvcNotify::ONDEREGISTERED );
- return 0;
- }
- }
- return 1;
- }
- #ifdef CBCLASS
- #undef CBCLASS
- #endif
- #define CBCLASS ServiceManager
- START_DISPATCH;
- CB( API_SERVICE_SERVICE_REGISTER, service_register );
- CB( API_SERVICE_SERVICE_DEREGISTER, service_deregister );
- CB( API_SERVICE_SERVICE_GETNUMSERVICES, service_getNumServices );
- CB( API_SERVICE_SERVICE_ENUMSERVICE, service_enumService );
- CB( API_SERVICE_SERVICE_GETSERVICEBYGUID, service_getServiceByGuid );
- CB( API_SERVICE_SERVICE_LOCK, service_lock );
- CB( API_SERVICE_SERVICE_CLIENTLOCK, service_clientLock );
- CB( API_SERVICE_SERVICE_RELEASE, service_release );
- CB( API_SERVICE_SERVICE_GETTYPENAME, service_getTypeName );
- CB( API_SERVICE_SERVICE_UNLOCK, service_unlock );
- CB( API_SERVICE_ISVALID, service_isvalid );
- CB( API_SERVICE_COMPACT_DUPLICATES, service_compactDuplicates );
- END_DISPATCH;
- #undef CBCLASS
|