* 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
This commit is contained in:
Ingo Weinhold
2005-01-25 14:58:37 +00:00
parent 27bd55fdf3
commit 73895a69a0
2 changed files with 130 additions and 12 deletions
+100 -6
View File
@@ -3,6 +3,7 @@
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include <map>
#include <new> #include <new>
#include <string.h> #include <string.h>
@@ -12,6 +13,9 @@
#include "Debug.h" #include "Debug.h"
#include "MessagingService.h" #include "MessagingService.h"
// sService -- the singleton instance
MessagingService *MessagingService::sService = NULL;
// constructor // constructor
MessagingArea::MessagingArea() MessagingArea::MessagingArea()
{ {
@@ -27,10 +31,10 @@ MessagingArea::~MessagingArea()
// Create // Create
status_t status_t
MessagingArea::Create(area_id kernelAreaID, sem_id lockSem, sem_id counterSem, MessagingArea::Create(area_id kernelAreaID, sem_id lockSem, sem_id counterSem,
MessagingArea *&area) MessagingArea *&_area)
{ {
// allocate the object on the heap // allocate the object on the heap
area = new(nothrow) MessagingArea; MessagingArea *area = new(nothrow) MessagingArea;
if (!area) if (!area)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -49,6 +53,7 @@ MessagingArea::Create(area_id kernelAreaID, sem_id lockSem, sem_id counterSem,
area->fCounterSem = counterSem; area->fCounterSem = counterSem;
area->fNextArea = NULL; area->fNextArea = NULL;
_area = area;
return B_OK; return B_OK;
} }
@@ -144,11 +149,17 @@ MessagingArea::NextArea() const
// #pragma mark - // #pragma mark -
// CommandHandlerMap
struct MessagingService::CommandHandlerMap
: map<uint32, MessagingCommandHandler*> {
};
// constructor // constructor
MessagingService::MessagingService() MessagingService::MessagingService()
: fLockSem(-1), : fLockSem(-1),
fCounterSem(-1), fCounterSem(-1),
fFirstArea(NULL), fFirstArea(NULL),
fCommandHandlers(NULL),
fCommandProcessor(-1), fCommandProcessor(-1),
fTerminating(false) fTerminating(false)
{ {
@@ -169,6 +180,8 @@ MessagingService::~MessagingService()
wait_for_thread(fCommandProcessor, &result); wait_for_thread(fCommandProcessor, &result);
} }
delete fCommandHandlers;
delete fFirstArea; delete fFirstArea;
} }
@@ -185,6 +198,11 @@ MessagingService::Init()
if (fCounterSem < 0) if (fCounterSem < 0)
return fCounterSem; return fCounterSem;
// create the command handler map
fCommandHandlers = new(nothrow) CommandHandlerMap;
if (!fCommandHandlers)
return B_NO_MEMORY;
// spawn the command processor // spawn the command processor
fCommandProcessor = spawn_thread(MessagingService::_CommandProcessorEntry, fCommandProcessor = spawn_thread(MessagingService::_CommandProcessorEntry,
"messaging command processor", B_DISPLAY_PRIORITY, this); "messaging command processor", B_DISPLAY_PRIORITY, this);
@@ -204,9 +222,75 @@ MessagingService::Init()
return error; return error;
} }
// resume the command processor
resume_thread(fCommandProcessor);
return B_OK; 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 // _CommandProcessorEntry
int32 int32
MessagingService::_CommandProcessorEntry(void *data) MessagingService::_CommandProcessorEntry(void *data)
@@ -218,11 +302,15 @@ MessagingService::_CommandProcessorEntry(void *data)
int32 int32
MessagingService::_CommandProcessor() MessagingService::_CommandProcessor()
{ {
bool commandWaiting = false;
while (!fTerminating) { while (!fTerminating) {
// wait for the next command // wait for the next command
status_t error = acquire_sem(fCounterSem); if (!commandWaiting) {
if (error != B_OK) status_t error = acquire_sem(fCounterSem);
continue; if (error != B_OK)
continue;
} else
commandWaiting = false;
// get it from the first area // get it from the first area
MessagingArea *area = fFirstArea; MessagingArea *area = fFirstArea;
@@ -238,7 +326,12 @@ MessagingService::_CommandProcessor()
} }
// dispatch the command // 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 // there is a new area we don't know yet
@@ -249,6 +342,7 @@ MessagingService::_CommandProcessor()
fLockSem, fCounterSem, nextArea); fLockSem, fCounterSem, nextArea);
if (error == B_OK) { if (error == B_OK) {
area->SetNextArea(nextArea); area->SetNextArea(nextArea);
commandWaiting = true;
} else { } else {
// Bad, but what can we do? // Bad, but what can we do?
ERROR(("MessagingService::_CommandProcessor(): Failed to clone " ERROR(("MessagingService::_CommandProcessor(): Failed to clone "
+30 -6
View File
@@ -8,6 +8,16 @@
#include <MessagingServiceDefs.h> #include <MessagingServiceDefs.h>
// MessagingCommandHandler
class MessagingCommandHandler {
public:
MessagingCommandHandler();
virtual ~MessagingCommandHandler();
virtual void HandleMessagingCommand(uint32 command, const void *data,
int32 dataSize) = 0;
};
// MessagingArea // MessagingArea
class MessagingArea { class MessagingArea {
public: public:
@@ -44,21 +54,35 @@ private:
// MessagingService // MessagingService
class MessagingService { class MessagingService {
public: private:
MessagingService(); MessagingService();
~MessagingService(); ~MessagingService();
status_t Init(); status_t Init();
public:
static status_t CreateDefault();
static void DeleteDefault();
static MessagingService *Default();
void SetCommandHandler(uint32 command, MessagingCommandHandler *handler);
private: private:
MessagingCommandHandler *_GetCommandHandler(uint32 command) const;
static int32 _CommandProcessorEntry(void *data); static int32 _CommandProcessorEntry(void *data);
int32 _CommandProcessor(); int32 _CommandProcessor();
sem_id fLockSem; struct CommandHandlerMap;
sem_id fCounterSem;
MessagingArea *fFirstArea; static MessagingService *sService;
thread_id fCommandProcessor;
volatile bool fTerminating; sem_id fLockSem;
sem_id fCounterSem;
MessagingArea *fFirstArea;
CommandHandlerMap *fCommandHandlers;
thread_id fCommandProcessor;
volatile bool fTerminating;
}; };
#endif // MESSAGING_SERVICE_H #endif // MESSAGING_SERVICE_H