#include <Message.h>
#include "PriorityMessageQueue.h"
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;
};
PriorityMessageQueue::PriorityMessageQueue()
: fLock(),
fMessages(20, true)
{
}
PriorityMessageQueue::~PriorityMessageQueue()
{
for (int32 i = 0; MessageInfo *info = fMessages.ItemAt(i); i++)
delete info->Message();
}
bool
PriorityMessageQueue::Lock()
{
return fLock.Lock();
}
void
PriorityMessageQueue::Unlock()
{
fLock.Unlock();
}
bool
PriorityMessageQueue::PushMessage(BMessage *message, int32 priority)
{
bool result = (message);
if (result)
result = Lock();
if (result) {
if (MessageInfo *info = new MessageInfo(message, priority)) {
int32 index = _FindInsertionIndex(priority);
if (!fMessages.AddItem(info, index)) {
result = false;
delete info;
}
} else
result = false;
Unlock();
}
return result;
}
BMessage *
PriorityMessageQueue::PopMessage()
{
BMessage *result = NULL;
if (Lock()) {
if (MessageInfo *info = fMessages.RemoveItemAt(0)) {
result = info->Message();
delete info;
}
Unlock();
}
return result;
}
int32
PriorityMessageQueue::CountMessages() const
{
int32 result = 0;
if (fLock.Lock()) {
result = fMessages.CountItems();
fLock.Unlock();
}
return result;
}
bool
PriorityMessageQueue::IsEmpty() const
{
return (CountMessages() == 0);
}
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;
}