From 73895a69a034a7bbcbacd7e578c94ac34077f961 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Tue, 25 Jan 2005 14:58:37 +0000 Subject: [PATCH] * Added the class MessagingCommandHandler, instances of which can be registered as handlers for specific commands sent by the kernel. (Beautifully object-oriented :-) * Fixed a bug regarding MessageArea creation (the object was deleted twice on error). * Actually resume the command processor thread. * Turned the class into a singleton. * Now always process all commands found in an area (should minimize latencies). Modulo bugs the class is now complete. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11027 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/registrar/MessagingService.cpp | 106 +++++++++++++++++++-- src/servers/registrar/MessagingService.h | 36 +++++-- 2 files changed, 130 insertions(+), 12 deletions(-) diff --git a/src/servers/registrar/MessagingService.cpp b/src/servers/registrar/MessagingService.cpp index 5fe698447d..aaf82d542b 100644 --- a/src/servers/registrar/MessagingService.cpp +++ b/src/servers/registrar/MessagingService.cpp @@ -3,6 +3,7 @@ * Distributed under the terms of the MIT License. */ +#include #include #include @@ -12,6 +13,9 @@ #include "Debug.h" #include "MessagingService.h" +// sService -- the singleton instance +MessagingService *MessagingService::sService = NULL; + // constructor MessagingArea::MessagingArea() { @@ -27,10 +31,10 @@ MessagingArea::~MessagingArea() // Create status_t MessagingArea::Create(area_id kernelAreaID, sem_id lockSem, sem_id counterSem, - MessagingArea *&area) + MessagingArea *&_area) { // allocate the object on the heap - area = new(nothrow) MessagingArea; + MessagingArea *area = new(nothrow) MessagingArea; if (!area) return B_NO_MEMORY; @@ -49,6 +53,7 @@ MessagingArea::Create(area_id kernelAreaID, sem_id lockSem, sem_id counterSem, area->fCounterSem = counterSem; area->fNextArea = NULL; + _area = area; return B_OK; } @@ -144,11 +149,17 @@ MessagingArea::NextArea() const // #pragma mark - +// CommandHandlerMap +struct MessagingService::CommandHandlerMap + : map { +}; + // constructor MessagingService::MessagingService() : fLockSem(-1), fCounterSem(-1), fFirstArea(NULL), + fCommandHandlers(NULL), fCommandProcessor(-1), fTerminating(false) { @@ -169,6 +180,8 @@ MessagingService::~MessagingService() wait_for_thread(fCommandProcessor, &result); } + delete fCommandHandlers; + delete fFirstArea; } @@ -185,6 +198,11 @@ MessagingService::Init() if (fCounterSem < 0) return fCounterSem; + // create the command handler map + fCommandHandlers = new(nothrow) CommandHandlerMap; + if (!fCommandHandlers) + return B_NO_MEMORY; + // spawn the command processor fCommandProcessor = spawn_thread(MessagingService::_CommandProcessorEntry, "messaging command processor", B_DISPLAY_PRIORITY, this); @@ -204,9 +222,75 @@ MessagingService::Init() return error; } + // resume the command processor + resume_thread(fCommandProcessor); + return B_OK; } +// CreateDefault +status_t +MessagingService::CreateDefault() +{ + if (sService) + return B_OK; + + // create the service + MessagingService *service = new(nothrow) MessagingService; + if (!service) + return B_NO_MEMORY; + + // init it + status_t error = service->Init(); + if (error != B_OK) { + delete service; + return error; + } + + sService = service; + return B_OK; +} + +// DeleteDefault +void +MessagingService::DeleteDefault() +{ + if (sService) { + delete sService; + sService = NULL; + } +} + +// Default +MessagingService * +MessagingService::Default() +{ + return sService; +} + +// SetCommandHandler +void +MessagingService::SetCommandHandler(uint32 command, + MessagingCommandHandler *handler) +{ + if (handler) { + (*fCommandHandlers)[command] = handler; + } else { + // no handler: remove and existing entry + CommandHandlerMap::iterator it = fCommandHandlers->find(command); + if (it != fCommandHandlers->end()) + fCommandHandlers->erase(it); + } +} + +// _GetCommandHandler +MessagingCommandHandler * +MessagingService::_GetCommandHandler(uint32 command) const +{ + CommandHandlerMap::iterator it = fCommandHandlers->find(command); + return (it != fCommandHandlers->end() ? it->second : NULL); +} + // _CommandProcessorEntry int32 MessagingService::_CommandProcessorEntry(void *data) @@ -218,11 +302,15 @@ MessagingService::_CommandProcessorEntry(void *data) int32 MessagingService::_CommandProcessor() { + bool commandWaiting = false; while (!fTerminating) { // wait for the next command - status_t error = acquire_sem(fCounterSem); - if (error != B_OK) - continue; + if (!commandWaiting) { + status_t error = acquire_sem(fCounterSem); + if (error != B_OK) + continue; + } else + commandWaiting = false; // get it from the first area MessagingArea *area = fFirstArea; @@ -238,7 +326,12 @@ MessagingService::_CommandProcessor() } // dispatch the command - // TODO: ... + MessagingCommandHandler *handler + = _GetCommandHandler(command->command); + if (handler) { + handler->HandleMessagingCommand(command->command, command->data, + command->size - sizeof(messaging_command)); + } } // there is a new area we don't know yet @@ -249,6 +342,7 @@ MessagingService::_CommandProcessor() fLockSem, fCounterSem, nextArea); if (error == B_OK) { area->SetNextArea(nextArea); + commandWaiting = true; } else { // Bad, but what can we do? ERROR(("MessagingService::_CommandProcessor(): Failed to clone " diff --git a/src/servers/registrar/MessagingService.h b/src/servers/registrar/MessagingService.h index bd959f3b8e..22a40ebccb 100644 --- a/src/servers/registrar/MessagingService.h +++ b/src/servers/registrar/MessagingService.h @@ -8,6 +8,16 @@ #include +// MessagingCommandHandler +class MessagingCommandHandler { +public: + MessagingCommandHandler(); + virtual ~MessagingCommandHandler(); + + virtual void HandleMessagingCommand(uint32 command, const void *data, + int32 dataSize) = 0; +}; + // MessagingArea class MessagingArea { public: @@ -44,21 +54,35 @@ private: // MessagingService class MessagingService { -public: +private: MessagingService(); ~MessagingService(); status_t Init(); +public: + static status_t CreateDefault(); + static void DeleteDefault(); + static MessagingService *Default(); + + void SetCommandHandler(uint32 command, MessagingCommandHandler *handler); + private: + MessagingCommandHandler *_GetCommandHandler(uint32 command) const; + static int32 _CommandProcessorEntry(void *data); int32 _CommandProcessor(); - sem_id fLockSem; - sem_id fCounterSem; - MessagingArea *fFirstArea; - thread_id fCommandProcessor; - volatile bool fTerminating; + struct CommandHandlerMap; + + static MessagingService *sService; + + sem_id fLockSem; + sem_id fCounterSem; + MessagingArea *fFirstArea; + CommandHandlerMap *fCommandHandlers; + thread_id fCommandProcessor; + volatile bool fTerminating; }; #endif // MESSAGING_SERVICE_H