diff --git a/src/servers/registrar/PriorityMessageQueue.cpp b/src/servers/registrar/PriorityMessageQueue.cpp new file mode 100644 index 0000000000..7e226b334f --- /dev/null +++ b/src/servers/registrar/PriorityMessageQueue.cpp @@ -0,0 +1,130 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- + +#include + +#include "PriorityMessageQueue.h" + +// MessageInfo +class PriorityMessageQueue::MessageInfo { +public: + MessageInfo(BMessage *message, int32 priority) + : fMessage(message), + fPriority(priority) + { + } + + BMessage *Message() const { return fMessage; } + int32 Priority() const { return fPriority; } + +private: + BMessage *fMessage; + int32 fPriority; +}; + + +// constructor +PriorityMessageQueue::PriorityMessageQueue() + : fLock(), + fMessages(20, true) +{ +} + +// destructor +PriorityMessageQueue::~PriorityMessageQueue() +{ + // delete the messages + for (int32 i = 0; MessageInfo *info = fMessages.ItemAt(i); i++) + delete info->Message(); + // the infos are deleted automatically +} + +// Lock +bool +PriorityMessageQueue::Lock() +{ + return fLock.Lock(); +} + +// Unlock +void +PriorityMessageQueue::Unlock() +{ + fLock.Unlock(); +} + +// PushMessage +bool +PriorityMessageQueue::PushMessage(BMessage *message, int32 priority) +{ + bool result = (message); + if (result) + result = Lock(); + if (result) { + if (MessageInfo *info = new MessageInfo(message, priority)) { + // find the insertion index + int32 index = _FindInsertionIndex(priority); + if (!fMessages.AddItem(info, index)) { + result = false; + delete info; + } + } else // no memory + result = false; + Unlock(); + } + return result; +} + +// PopMessage +BMessage * +PriorityMessageQueue::PopMessage() +{ + BMessage *result = NULL; + if (Lock()) { + if (MessageInfo *info = fMessages.RemoveItemAt(0)) { + result = info->Message(); + delete info; + } + Unlock(); + } + return result; +} + +// CountMessages +int32 +PriorityMessageQueue::CountMessages() const +{ + int32 result = 0; + if (fLock.Lock()) { + result = fMessages.CountItems(); + fLock.Unlock(); + } + return result; +} + +// IsEmpty +bool +PriorityMessageQueue::IsEmpty() const +{ + return (CountMessages() == 0); +} + +// _FindInsertionIndex +int32 +PriorityMessageQueue::_FindInsertionIndex(int32 priority) +{ + int32 lower = 0; + int32 upper = fMessages.CountItems(); + while (lower < upper) { + int32 mid = (lower + upper) / 2; + MessageInfo *info = fMessages.ItemAt(mid); + if (info->Priority() >= priority) + lower = mid + 1; + else + upper = mid; + } + return lower; +} + diff --git a/src/servers/registrar/PriorityMessageQueue.h b/src/servers/registrar/PriorityMessageQueue.h new file mode 100644 index 0000000000..83c1fefc6f --- /dev/null +++ b/src/servers/registrar/PriorityMessageQueue.h @@ -0,0 +1,39 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- + +#ifndef PRIORITY_MESSAGE_QUEUE_H +#define PRIORITY_MESSAGE_QUEUE_H + +#include +#include + +class BMessage; + +class PriorityMessageQueue { +public: + PriorityMessageQueue(); + ~PriorityMessageQueue(); + + bool Lock(); + void Unlock(); + + bool PushMessage(BMessage *message, int32 priority = 0); + BMessage *PopMessage(); + + int32 CountMessages() const; + bool IsEmpty() const; + +private: + int32 _FindInsertionIndex(int32 priority); + +private: + class MessageInfo; + +private: + mutable BLocker fLock; + BObjectList fMessages; +}; + +#endif // PRIORITY_MESSAGE_QUEUE_H