#include "ServiceManager.h" #include "api__wasabi-replicant.h" #include "service/ifc_servicefactory.h" #include "service/svccb.h" using namespace nu; ServiceManager::ServiceManager() { #ifdef _WIN32 component_wait = CreateSemaphoreW(NULL, 0, LONG_MAX, NULL); #else sem_init(&component_wait, 0, 0); #endif } ServiceManager::~ServiceManager() { #ifdef _WIN32 if (component_wait) CloseHandle(component_wait); #else sem_destroy(&component_wait); #endif } int ServiceManager::Dispatchable_QueryInterface(GUID interface_guid, void **object) { if (interface_guid == ifc_component_sync::GetInterfaceGUID()) { *object = (ifc_component_sync *)this; } return NErr_Unknown; } //------------------------------------------- int ServiceManager::GetServiceIndex(GUID key) { for(int idx = 0; idx < services_indexer.size(); idx++) { if (memcmp(&key, &services_indexer[idx], sizeof(GUID)) == 0) { return idx; } } return -1; } int ServiceManager::Service_Register(ifc_serviceFactory *svc) { AutoLock lock(serviceGuard LOCKNAME("ServiceManager::service_register")); GUID service_type = svc->GetServiceType(); GUID service_id = svc->GetGUID(); // add the service to the master list ifc_serviceFactory* new_factory = services[service_id]; if (new_factory) // if someone already has this GUID, we need to replace { // replace factory in services_by_type map ServiceList* type_list = services_by_type[service_type]; if (type_list) { for (ServiceList::iterator itr=type_list->begin();itr!=type_list->end();itr++) { ifc_serviceFactory *f = *itr; if (f->GetGUID() == service_id) { *itr = svc; } } } // tell the old factory we're kicking its ass to the curb. new_factory->ServiceNotify(ifc_serviceFactory::ONUNREGISTERED); // HAKAN: // Should we delete old factory? // new_factory = svc; } else // not used yet, just assign { //new_factory = svc; services_indexer.push_back(service_id); // 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); } services[service_id]=svc; // send notifications svc->ServiceNotify(ifc_serviceFactory::ONREGISTERED); WASABI2_API_SYSCB->IssueCallback(Service::event_type, Service::on_register, (intptr_t)&service_type, reinterpret_cast(svc)); return NErr_Success; } int ServiceManager::Service_Unregister(ifc_serviceFactory *svc) { AutoLock lock(serviceGuard LOCKNAME("ServiceManager::Service_Unregister")); GUID service_type = svc->GetServiceType(); GUID service_id = svc->GetGUID(); // remove it from the master list ServiceMap::iterator itr = services.find(service_id); if (itr != services.end()) services.erase(itr); // and from the type lookup map ServiceList *type_list = services_by_type[service_type]; if (type_list) { //type_list->eraseObject(svc); for (auto it = type_list->begin(); it != type_list->end(); it++) { if (*it == svc) { it = type_list->erase(it); break; } } } WASABI2_API_SYSCB->IssueCallback(Service::event_type, Service::on_deregister, (intptr_t)&service_type, reinterpret_cast(svc)); svc->ServiceNotify(ifc_serviceFactory::ONUNREGISTERED); return NErr_Success; } size_t ServiceManager::Service_GetServiceCount(GUID svc_type) { AutoLock lock(serviceGuard LOCKNAME("ServiceManager::Service_GetServiceCount")); ServiceList *type_list = services_by_type[svc_type]; if (type_list) return type_list->size(); else return 0; } ifc_serviceFactory *ServiceManager::Service_EnumService(GUID svc_type, size_t n) { AutoLock lock(serviceGuard LOCKNAME("ServiceManager::Service_EnumService")); ServiceList *type_list = services_by_type[svc_type]; if (type_list && (size_t)n < type_list->size()) return type_list->at(n); else return 0; } ifc_serviceFactory *ServiceManager::Service_EnumService(size_t n) { AutoLock lock(serviceGuard LOCKNAME("ServiceManager::Service_EnumService")); if ((size_t)n < services.size()) { //return services.at(n).second; if (n < services_indexer.size()) { GUID g = services_indexer[n]; return services[g]; } } return 0; } ifc_serviceFactory *ServiceManager::Service_GetServiceByGUID(GUID guid) { AutoLock lock(serviceGuard LOCKNAME("ServiceManager::service_getServiceByGuid")); ServiceMap::iterator itr = services.find(guid); if (itr != services.end()) return itr->second; else return 0; } void ServiceManager::Service_ComponentDone() { #ifdef _WIN32 ReleaseSemaphore(component_wait, 1, NULL); #else sem_post(&component_wait); #endif } int ServiceManager::ComponentSync_Wait(size_t count) { while (count--) { #ifdef _WIN32 WaitForSingleObject(component_wait, INFINITE); #else sem_wait(&component_wait); #endif } return NErr_Success; }