haiku/src/kits/app/MessageQueue.cpp

230 lines
3.6 KiB
C++

/*
* Copyright 2001-2014 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Unknown? Eric?
* Axel Dörfler, axeld@pinc-software.de
*/
// Queue for holding BMessages
#include <MessageQueue.h>
#include <Autolock.h>
#include <Message.h>
BMessageQueue::BMessageQueue()
:
fHead(NULL),
fTail(NULL),
fMessageCount(0),
fLock("BMessageQueue Lock")
{
}
BMessageQueue::~BMessageQueue()
{
if (!Lock())
return;
BMessage* message = fHead;
while (message != NULL) {
BMessage* next = message->fQueueLink;
delete message;
message = next;
}
}
void
BMessageQueue::AddMessage(BMessage* message)
{
if (message == NULL)
return;
BAutolock _(fLock);
if (!IsLocked())
return;
// The message passed in will be the last message on the queue so its
// link member should be set to null.
message->fQueueLink = NULL;
fMessageCount++;
if (fTail == NULL) {
// there are no messages in the queue yet
fHead = fTail = message;
} else {
// just add it after the tail
fTail->fQueueLink = message;
fTail = message;
}
}
void
BMessageQueue::RemoveMessage(BMessage* message)
{
if (message == NULL)
return;
BAutolock _(fLock);
if (!IsLocked())
return;
BMessage* last = NULL;
for (BMessage* entry = fHead; entry != NULL; entry = entry->fQueueLink) {
if (entry == message) {
// remove this one
if (entry == fHead)
fHead = entry->fQueueLink;
else
last->fQueueLink = entry->fQueueLink;
if (entry == fTail)
fTail = last;
fMessageCount--;
return;
}
last = entry;
}
}
int32
BMessageQueue::CountMessages() const
{
return fMessageCount;
}
bool
BMessageQueue::IsEmpty() const
{
return fMessageCount == 0;
}
BMessage*
BMessageQueue::FindMessage(int32 index) const
{
BAutolock _(fLock);
if (!IsLocked())
return NULL;
if (index < 0 || index >= fMessageCount)
return NULL;
for (BMessage* message = fHead; message != NULL; message = message->fQueueLink) {
// If the index reaches zero, then we have found a match.
if (index == 0)
return message;
index--;
}
return NULL;
}
BMessage*
BMessageQueue::FindMessage(uint32 what, int32 index) const
{
BAutolock _(fLock);
if (!IsLocked())
return NULL;
if (index < 0 || index >= fMessageCount)
return NULL;
for (BMessage* message = fHead; message != NULL; message = message->fQueueLink) {
if (message->what == what) {
// If the index reaches zero, then we have found a match.
if (index == 0)
return message;
index--;
}
}
return NULL;
}
bool
BMessageQueue::Lock()
{
return fLock.Lock();
}
void
BMessageQueue::Unlock()
{
fLock.Unlock();
}
bool
BMessageQueue::IsLocked() const
{
return fLock.IsLocked();
}
BMessage*
BMessageQueue::NextMessage()
{
BAutolock _(fLock);
if (!IsLocked())
return NULL;
// remove the head of the queue, if any, and return it
BMessage* head = fHead;
if (head == NULL)
return NULL;
fMessageCount--;
fHead = head->fQueueLink;
if (fHead == NULL) {
// If the queue is empty after removing the front element,
// we need to set the tail of the queue to NULL since the queue
// is now empty.
fTail = NULL;
}
return head;
}
bool
BMessageQueue::IsNextMessage(const BMessage* message) const
{
BAutolock _(fLock);
return fHead == message;
}
// This method is only here for R5 binary compatibility!
// It should be dropped as soon as possible (it misses the const qualifier).
bool
BMessageQueue::IsLocked()
{
return fLock.IsLocked();
}
void BMessageQueue::_ReservedMessageQueue1() {}
void BMessageQueue::_ReservedMessageQueue2() {}
void BMessageQueue::_ReservedMessageQueue3() {}