* 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:
@@ -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 "
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user