xref: /haiku/src/kits/app/MessageQueue.cpp (revision be902ac4db5c9d0be72f6d54aa67b66e3dcc7eca)
11ba67cc8SAxel Dörfler /*
2*be902ac4SJohn Scipione  * Copyright 2001-2014 Haiku, Inc. All rights reserved.
31ba67cc8SAxel Dörfler  * Distributed under the terms of the MIT License.
41ba67cc8SAxel Dörfler  *
51ba67cc8SAxel Dörfler  * Authors:
61ba67cc8SAxel Dörfler  *		Unknown? Eric?
71ba67cc8SAxel Dörfler  *		Axel Dörfler, axeld@pinc-software.de
81ba67cc8SAxel Dörfler  */
91ba67cc8SAxel Dörfler 
10*be902ac4SJohn Scipione 
11*be902ac4SJohn Scipione // Queue for holding BMessages
121ba67cc8SAxel Dörfler 
1352a38012Sejakowatz 
1430fd5147Shaydentech #include <MessageQueue.h>
1530fd5147Shaydentech #include <Autolock.h>
1630fd5147Shaydentech #include <Message.h>
1752a38012Sejakowatz 
1852a38012Sejakowatz 
BMessageQueue()1989bdf573SMarcus Overhagen BMessageQueue::BMessageQueue()
201ba67cc8SAxel Dörfler 	:
211ba67cc8SAxel Dörfler 	fHead(NULL),
221ba67cc8SAxel Dörfler 	fTail(NULL),
2389bdf573SMarcus Overhagen 	fMessageCount(0),
241ba67cc8SAxel Dörfler 	fLock("BMessageQueue Lock")
2552a38012Sejakowatz {
2652a38012Sejakowatz }
2752a38012Sejakowatz 
2852a38012Sejakowatz 
~BMessageQueue()2952a38012Sejakowatz BMessageQueue::~BMessageQueue()
3052a38012Sejakowatz {
311ba67cc8SAxel Dörfler 	if (!Lock())
321ba67cc8SAxel Dörfler 		return;
331ba67cc8SAxel Dörfler 
341ba67cc8SAxel Dörfler 	BMessage* message = fHead;
351ba67cc8SAxel Dörfler 	while (message != NULL) {
361ba67cc8SAxel Dörfler 		BMessage* next = message->fQueueLink;
371ba67cc8SAxel Dörfler 
381ba67cc8SAxel Dörfler 		delete message;
391ba67cc8SAxel Dörfler 		message = next;
4052a38012Sejakowatz 	}
4152a38012Sejakowatz }
4252a38012Sejakowatz 
4352a38012Sejakowatz 
4452a38012Sejakowatz void
AddMessage(BMessage * message)4552a38012Sejakowatz BMessageQueue::AddMessage(BMessage* message)
4652a38012Sejakowatz {
471ba67cc8SAxel Dörfler 	if (message == NULL)
4852a38012Sejakowatz 		return;
4952a38012Sejakowatz 
501ba67cc8SAxel Dörfler 	BAutolock _(fLock);
511ba67cc8SAxel Dörfler 	if (!IsLocked())
521ba67cc8SAxel Dörfler 		return;
5352a38012Sejakowatz 
5452a38012Sejakowatz 	// The message passed in will be the last message on the queue so its
5552a38012Sejakowatz 	// link member should be set to null.
56cf10934eSMichael Lotz 	message->fQueueLink = NULL;
5752a38012Sejakowatz 
5852a38012Sejakowatz 	fMessageCount++;
5952a38012Sejakowatz 
601ba67cc8SAxel Dörfler 	if (fTail == NULL) {
611ba67cc8SAxel Dörfler 		// there are no messages in the queue yet
621ba67cc8SAxel Dörfler 		fHead = fTail = message;
6352a38012Sejakowatz 	} else {
641ba67cc8SAxel Dörfler 		// just add it after the tail
651ba67cc8SAxel Dörfler 		fTail->fQueueLink = message;
661ba67cc8SAxel Dörfler 		fTail = message;
6752a38012Sejakowatz 	}
6852a38012Sejakowatz }
6952a38012Sejakowatz 
7052a38012Sejakowatz 
7152a38012Sejakowatz void
RemoveMessage(BMessage * message)7252a38012Sejakowatz BMessageQueue::RemoveMessage(BMessage* message)
7352a38012Sejakowatz {
741ba67cc8SAxel Dörfler 	if (message == NULL)
7552a38012Sejakowatz 		return;
7652a38012Sejakowatz 
771ba67cc8SAxel Dörfler 	BAutolock _(fLock);
781ba67cc8SAxel Dörfler 	if (!IsLocked())
791ba67cc8SAxel Dörfler 		return;
8052a38012Sejakowatz 
811ba67cc8SAxel Dörfler 	BMessage* last = NULL;
821ba67cc8SAxel Dörfler 	for (BMessage* entry = fHead; entry != NULL; entry = entry->fQueueLink) {
831ba67cc8SAxel Dörfler 		if (entry == message) {
841ba67cc8SAxel Dörfler 			// remove this one
851ba67cc8SAxel Dörfler 			if (entry == fHead)
861ba67cc8SAxel Dörfler 				fHead = entry->fQueueLink;
876338e9daSAxel Dörfler 			else
886338e9daSAxel Dörfler 				last->fQueueLink = entry->fQueueLink;
896338e9daSAxel Dörfler 
901ba67cc8SAxel Dörfler 			if (entry == fTail)
911ba67cc8SAxel Dörfler 				fTail = last;
9252a38012Sejakowatz 
9352a38012Sejakowatz 			fMessageCount--;
9452a38012Sejakowatz 			return;
9552a38012Sejakowatz 		}
961ba67cc8SAxel Dörfler 		last = entry;
9752a38012Sejakowatz 	}
9852a38012Sejakowatz }
9952a38012Sejakowatz 
10052a38012Sejakowatz 
10152a38012Sejakowatz int32
CountMessages() const1021ba67cc8SAxel Dörfler BMessageQueue::CountMessages() const
10352a38012Sejakowatz {
10452a38012Sejakowatz     return fMessageCount;
10552a38012Sejakowatz }
10652a38012Sejakowatz 
10752a38012Sejakowatz 
10852a38012Sejakowatz bool
IsEmpty() const1091ba67cc8SAxel Dörfler BMessageQueue::IsEmpty() const
11052a38012Sejakowatz {
1111ba67cc8SAxel Dörfler     return fMessageCount == 0;
11252a38012Sejakowatz }
11352a38012Sejakowatz 
11452a38012Sejakowatz 
11552a38012Sejakowatz BMessage*
FindMessage(int32 index) const11652a38012Sejakowatz BMessageQueue::FindMessage(int32 index) const
11752a38012Sejakowatz {
1181ba67cc8SAxel Dörfler 	BAutolock _(fLock);
1191ba67cc8SAxel Dörfler 	if (!IsLocked())
1201ba67cc8SAxel Dörfler 		return NULL;
1211ba67cc8SAxel Dörfler 
1221ba67cc8SAxel Dörfler 	if (index < 0 || index >= fMessageCount)
1231ba67cc8SAxel Dörfler 		return NULL;
1241ba67cc8SAxel Dörfler 
1251ba67cc8SAxel Dörfler 	for (BMessage* message = fHead; message != NULL; message = message->fQueueLink) {
1261ba67cc8SAxel Dörfler 		// If the index reaches zero, then we have found a match.
1271ba67cc8SAxel Dörfler 		if (index == 0)
1281ba67cc8SAxel Dörfler 			return message;
1291ba67cc8SAxel Dörfler 
1301ba67cc8SAxel Dörfler 		index--;
1311ba67cc8SAxel Dörfler 	}
1321ba67cc8SAxel Dörfler 
13352a38012Sejakowatz     return NULL;
13452a38012Sejakowatz }
13552a38012Sejakowatz 
13652a38012Sejakowatz 
13752a38012Sejakowatz BMessage*
FindMessage(uint32 what,int32 index) const1381ba67cc8SAxel Dörfler BMessageQueue::FindMessage(uint32 what, int32 index) const
13952a38012Sejakowatz {
1401ba67cc8SAxel Dörfler 	BAutolock _(fLock);
1411ba67cc8SAxel Dörfler 	if (!IsLocked())
1421ba67cc8SAxel Dörfler 		return NULL;
1431ba67cc8SAxel Dörfler 
1441ba67cc8SAxel Dörfler 	if (index < 0 || index >= fMessageCount)
1451ba67cc8SAxel Dörfler 		return NULL;
1461ba67cc8SAxel Dörfler 
1471ba67cc8SAxel Dörfler 	for (BMessage* message = fHead; message != NULL; message = message->fQueueLink) {
1481ba67cc8SAxel Dörfler 		if (message->what == what) {
1491ba67cc8SAxel Dörfler 			// If the index reaches zero, then we have found a match.
1501ba67cc8SAxel Dörfler 			if (index == 0)
1511ba67cc8SAxel Dörfler 				return message;
1521ba67cc8SAxel Dörfler 
1531ba67cc8SAxel Dörfler 			index--;
1541ba67cc8SAxel Dörfler 		}
1551ba67cc8SAxel Dörfler 	}
1561ba67cc8SAxel Dörfler 
15752a38012Sejakowatz     return NULL;
15852a38012Sejakowatz }
15952a38012Sejakowatz 
16052a38012Sejakowatz 
16152a38012Sejakowatz bool
Lock()1621ba67cc8SAxel Dörfler BMessageQueue::Lock()
16352a38012Sejakowatz {
1641ba67cc8SAxel Dörfler     return fLock.Lock();
16552a38012Sejakowatz }
16652a38012Sejakowatz 
16752a38012Sejakowatz 
16852a38012Sejakowatz void
Unlock()1691ba67cc8SAxel Dörfler BMessageQueue::Unlock()
17052a38012Sejakowatz {
1711ba67cc8SAxel Dörfler 	fLock.Unlock();
17252a38012Sejakowatz }
17352a38012Sejakowatz 
17452a38012Sejakowatz 
17552a38012Sejakowatz bool
IsLocked() const1761ba67cc8SAxel Dörfler BMessageQueue::IsLocked() const
17752a38012Sejakowatz {
1781ba67cc8SAxel Dörfler 	return fLock.IsLocked();
17952a38012Sejakowatz }
18052a38012Sejakowatz 
18152a38012Sejakowatz 
18252a38012Sejakowatz BMessage*
NextMessage()1831ba67cc8SAxel Dörfler BMessageQueue::NextMessage()
18452a38012Sejakowatz {
1851ba67cc8SAxel Dörfler 	BAutolock _(fLock);
1861ba67cc8SAxel Dörfler 	if (!IsLocked())
1871ba67cc8SAxel Dörfler 		return NULL;
18852a38012Sejakowatz 
1891ba67cc8SAxel Dörfler 	// remove the head of the queue, if any, and return it
19052a38012Sejakowatz 
1911ba67cc8SAxel Dörfler 	BMessage* head = fHead;
1921ba67cc8SAxel Dörfler 	if (head == NULL)
1931ba67cc8SAxel Dörfler 		return NULL;
1941ba67cc8SAxel Dörfler 
19552a38012Sejakowatz 	fMessageCount--;
1961ba67cc8SAxel Dörfler 	fHead = head->fQueueLink;
1971ba67cc8SAxel Dörfler 
1981ba67cc8SAxel Dörfler 	if (fHead == NULL) {
1991ba67cc8SAxel Dörfler 		// If the queue is empty after removing the front element,
2001ba67cc8SAxel Dörfler 		// we need to set the tail of the queue to NULL since the queue
20152a38012Sejakowatz 		// is now empty.
2021ba67cc8SAxel Dörfler 		fTail = NULL;
20352a38012Sejakowatz 	}
2041ba67cc8SAxel Dörfler 
2051ba67cc8SAxel Dörfler 	return head;
20652a38012Sejakowatz }
20752a38012Sejakowatz 
20852a38012Sejakowatz 
209ca9b9188SAxel Dörfler bool
IsNextMessage(const BMessage * message) const210ca9b9188SAxel Dörfler BMessageQueue::IsNextMessage(const BMessage* message) const
211ca9b9188SAxel Dörfler {
212ca9b9188SAxel Dörfler 	BAutolock _(fLock);
213ca9b9188SAxel Dörfler 	return fHead == message;
214ca9b9188SAxel Dörfler }
215ca9b9188SAxel Dörfler 
216ca9b9188SAxel Dörfler 
217*be902ac4SJohn Scipione // This method is only here for R5 binary compatibility!
218*be902ac4SJohn Scipione // It should be dropped as soon as possible (it misses the const qualifier).
2191ba67cc8SAxel Dörfler bool
IsLocked()2201ba67cc8SAxel Dörfler BMessageQueue::IsLocked()
22152a38012Sejakowatz {
2221ba67cc8SAxel Dörfler 	return fLock.IsLocked();
22352a38012Sejakowatz }
22452a38012Sejakowatz 
22552a38012Sejakowatz 
_ReservedMessageQueue1()2261ba67cc8SAxel Dörfler void BMessageQueue::_ReservedMessageQueue1() {}
_ReservedMessageQueue2()2271ba67cc8SAxel Dörfler void BMessageQueue::_ReservedMessageQueue2() {}
_ReservedMessageQueue3()2281ba67cc8SAxel Dörfler void BMessageQueue::_ReservedMessageQueue3() {}
22952a38012Sejakowatz 
230