* 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

View File

@ -3,6 +3,7 @@
* Distributed under the terms of the MIT License.
*/
#include <map>
#include <new>
#include <string.h>
@ -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<uint32, MessagingCommandHandler*> {
};
// 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 "

View File

@ -8,6 +8,16 @@
#include <MessagingServiceDefs.h>
// 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