xref: /haiku/src/kits/app/MessageQueue.cpp (revision cf10934e5fde37c267f7fb3bec89a8e9f5d9c476)
176441babSDarkWyrm //------------------------------------------------------------------------------
276441babSDarkWyrm //	Copyright (c) 2001-2002, OpenBeOS
352a38012Sejakowatz //
476441babSDarkWyrm //	Permission is hereby granted, free of charge, to any person obtaining a
576441babSDarkWyrm //	copy of this software and associated documentation files (the "Software"),
676441babSDarkWyrm //	to deal in the Software without restriction, including without limitation
776441babSDarkWyrm //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
876441babSDarkWyrm //	and/or sell copies of the Software, and to permit persons to whom the
976441babSDarkWyrm //	Software is furnished to do so, subject to the following conditions:
1052a38012Sejakowatz //
1176441babSDarkWyrm //	The above copyright notice and this permission notice shall be included in
1276441babSDarkWyrm //	all copies or substantial portions of the Software.
1352a38012Sejakowatz //
1476441babSDarkWyrm //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1576441babSDarkWyrm //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1676441babSDarkWyrm //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1776441babSDarkWyrm //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1876441babSDarkWyrm //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1976441babSDarkWyrm //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2076441babSDarkWyrm //	DEALINGS IN THE SOFTWARE.
2176441babSDarkWyrm //
2276441babSDarkWyrm //	File Name:		MessageQueue.cpp
2376441babSDarkWyrm //	Author(s):		unknown
2476441babSDarkWyrm //
2576441babSDarkWyrm //	Description:	Queue for holding BMessages
2676441babSDarkWyrm //
2776441babSDarkWyrm //------------------------------------------------------------------------------
2852a38012Sejakowatz 
2930fd5147Shaydentech #include <MessageQueue.h>
3030fd5147Shaydentech #include <Autolock.h>
3130fd5147Shaydentech #include <Message.h>
3252a38012Sejakowatz 
3352a38012Sejakowatz #ifdef USE_OPENBEOS_NAMESPACE
3452a38012Sejakowatz namespace OpenBeOS {
3552a38012Sejakowatz #endif
3652a38012Sejakowatz 
3752a38012Sejakowatz 
3852a38012Sejakowatz /*
3952a38012Sejakowatz  *  Method: BMessageQueue::BMessageQueue()
4052a38012Sejakowatz  *   Descr: This method is the only constructor for a BMessageQueue.  Once the
4152a38012Sejakowatz  *          constructor completes, the BMessageQueue is created with no BMessages
4252a38012Sejakowatz  *          in it.
4352a38012Sejakowatz  *
4452a38012Sejakowatz  */
4589bdf573SMarcus Overhagen BMessageQueue::BMessageQueue()
4689bdf573SMarcus Overhagen  :	fTheQueue(NULL),
4789bdf573SMarcus Overhagen  	fQueueTail(NULL),
4889bdf573SMarcus Overhagen  	fMessageCount(0),
4989bdf573SMarcus Overhagen  	fLocker("BMessageQueue_fLocker")
5052a38012Sejakowatz {
5152a38012Sejakowatz }
5252a38012Sejakowatz 
5352a38012Sejakowatz 
5452a38012Sejakowatz /*
5552a38012Sejakowatz  *  Method: BMessageQueue::~BMessageQueue()
5652a38012Sejakowatz  *   Descr: This is the desctructor for the BMessageQueue.  It iterates over
5752a38012Sejakowatz  *          any messages left on the queue and deletes them.
5852a38012Sejakowatz  *
5952a38012Sejakowatz  *		    The implementation is careful not to release the lock when the
6052a38012Sejakowatz  *          BMessageQueue is deconstructed.  If the lock is released, it is
6152a38012Sejakowatz  *          possible another thread will start an AddMessage() operation before
6252a38012Sejakowatz  *          the BLocker is deleted.  The safe thing to do is not to unlock the
6352a38012Sejakowatz  *          BLocker from the destructor once it is acquired. That way, any thread
6452a38012Sejakowatz  *          waiting to do a AddMessage() will fail to acquire the lock since the
6552a38012Sejakowatz  *          BLocker will be deleted before they can acquire it.
6652a38012Sejakowatz  *
6752a38012Sejakowatz  */
6852a38012Sejakowatz BMessageQueue::~BMessageQueue()
6952a38012Sejakowatz {
7052a38012Sejakowatz 	if (fLocker.Lock()) {
7152a38012Sejakowatz 		BMessage *theMessage = fTheQueue;
7252a38012Sejakowatz 		while (theMessage != NULL) {
7352a38012Sejakowatz 			BMessage *messageToDelete = theMessage;
74*cf10934eSMichael Lotz #ifndef USING_MESSAGE4
7552a38012Sejakowatz 			theMessage = theMessage->link;
76*cf10934eSMichael Lotz #else
77*cf10934eSMichael Lotz 			theMessage = theMessage->fQueueLink;
78*cf10934eSMichael Lotz #endif
7952a38012Sejakowatz 			delete messageToDelete;
8052a38012Sejakowatz 		}
8152a38012Sejakowatz 	}
8252a38012Sejakowatz }
8352a38012Sejakowatz 
8452a38012Sejakowatz 
8552a38012Sejakowatz /*
8652a38012Sejakowatz  *  Method: BMessageQueue::AddMessage()
8752a38012Sejakowatz  *   Descr: This method adds a BMessage to the queue.  It makes a couple of
8852a38012Sejakowatz  *          assumptions:
8952a38012Sejakowatz  *             - The BMessage was allocated on the heap with new.  Since the
9052a38012Sejakowatz  *               destructor delete's BMessages left on the queue, this must be
9152a38012Sejakowatz  *               true.  The same assumption is made with Be's implementation.
9252a38012Sejakowatz  *             - The BMessage is not already on this or any other BMessageQueue.
9352a38012Sejakowatz  *               If it is, the queue it is already on will be corrupted.  Be's
9452a38012Sejakowatz  *               implementation makes this assumption also and does corrupt
9552a38012Sejakowatz  *               BMessageQueues where this is violated.
9652a38012Sejakowatz  *
9752a38012Sejakowatz  */
9852a38012Sejakowatz void
9952a38012Sejakowatz BMessageQueue::AddMessage(BMessage *message)
10052a38012Sejakowatz {
10152a38012Sejakowatz 	if (message == NULL) {
10252a38012Sejakowatz 		return;
10352a38012Sejakowatz 	}
10452a38012Sejakowatz 
10552a38012Sejakowatz 	// The Be implementation does not seem to check that the lock acquisition
10652a38012Sejakowatz 	// was successful.  This will specifically cause problems when the
10752a38012Sejakowatz 	// message queue is deleted.  On delete, any thread waiting for the lock
10852a38012Sejakowatz 	// will be notified that the lock failed.  Be's implementation, because
10952a38012Sejakowatz 	// they do not check proceeds with the operation, potentially corrupting
11052a38012Sejakowatz 	// memory.  This implementation is different, but I can't imagine that
11152a38012Sejakowatz 	// Be's implementation is worth emulating.
11252a38012Sejakowatz 	//
11352a38012Sejakowatz 	BAutolock theAutoLocker(fLocker);
11452a38012Sejakowatz 
11552a38012Sejakowatz 	if (theAutoLocker.IsLocked()) {
11652a38012Sejakowatz 
11752a38012Sejakowatz 		// The message passed in will be the last message on the queue so its
11852a38012Sejakowatz 		// link member should be set to null.
119*cf10934eSMichael Lotz #ifndef USING_MESSAGE4
12052a38012Sejakowatz 		message->link = NULL;
121*cf10934eSMichael Lotz #else
122*cf10934eSMichael Lotz 		message->fQueueLink = NULL;
123*cf10934eSMichael Lotz #endif
12452a38012Sejakowatz 
12552a38012Sejakowatz 		// We now have one more BMessage on the queue.
12652a38012Sejakowatz 		fMessageCount++;
12752a38012Sejakowatz 
12852a38012Sejakowatz 		// If there are no BMessages on the queue.
12952a38012Sejakowatz 		if (fQueueTail == NULL) {
13052a38012Sejakowatz 			// Then this message is both the start and the end of the queue.
13152a38012Sejakowatz 			fTheQueue = message;
13252a38012Sejakowatz 			fQueueTail = message;
13352a38012Sejakowatz 		} else {
13452a38012Sejakowatz 			// If there are already messages on the queue, then the put this
13552a38012Sejakowatz 			// BMessage at the end.  The last BMessage prior to this AddMessage()
13652a38012Sejakowatz 			// is fQueueTail.  The BMessage at fQueueTail needs to point to the
13752a38012Sejakowatz 			// new last message, the one being added.
138*cf10934eSMichael Lotz #ifndef USING_MESSAGE4
13952a38012Sejakowatz 			fQueueTail->link = message;
140*cf10934eSMichael Lotz #else
141*cf10934eSMichael Lotz 			fQueueTail->fQueueLink = message;
142*cf10934eSMichael Lotz #endif
14352a38012Sejakowatz 
14452a38012Sejakowatz 			// Now update the fQueueTail to point to this new last message.
14552a38012Sejakowatz 			fQueueTail = message;
14652a38012Sejakowatz 		}
14752a38012Sejakowatz 	}
14852a38012Sejakowatz }
14952a38012Sejakowatz 
15052a38012Sejakowatz 
15152a38012Sejakowatz /*
15252a38012Sejakowatz  *  Method: BMessageQueue::RemoveMessage()
15352a38012Sejakowatz  *   Descr: This method searches the queue for a particular BMessage.  If
15452a38012Sejakowatz  *          it is found, it is removed from the queue.
15552a38012Sejakowatz  *
15652a38012Sejakowatz  */
15752a38012Sejakowatz void
15852a38012Sejakowatz BMessageQueue::RemoveMessage(BMessage *message)
15952a38012Sejakowatz {
16052a38012Sejakowatz 	if (message == NULL) {
16152a38012Sejakowatz 		return;
16252a38012Sejakowatz 	}
16352a38012Sejakowatz 
16452a38012Sejakowatz 	BAutolock theAutoLocker(fLocker);
16552a38012Sejakowatz 
16652a38012Sejakowatz 	// The Be implementation does not seem to check that the lock acquisition
16752a38012Sejakowatz 	// was successful.  This will specifically cause problems when the
16852a38012Sejakowatz 	// message queue is deleted.  On delete, any thread waiting for the lock
16952a38012Sejakowatz 	// will be notified that the lock failed.  Be's implementation, because
17052a38012Sejakowatz 	// they do not check proceeds with the operation, potentially corrupting
17152a38012Sejakowatz 	// memory.  This implementation is different, but I can't imagine that
17252a38012Sejakowatz 	// Be's implementation is worth emulating.
17352a38012Sejakowatz 	//
17452a38012Sejakowatz 	if (theAutoLocker.IsLocked()) {
17552a38012Sejakowatz 
17652a38012Sejakowatz 		// If the message to be removed is at the front of the queue.
17752a38012Sejakowatz 		if (fTheQueue == message) {
17852a38012Sejakowatz 			// We need to special case the handling of removing the first element.
17952a38012Sejakowatz 			// First, the new front element will be the next one.
180*cf10934eSMichael Lotz #ifndef USING_MESSAGE4
18152a38012Sejakowatz 			fTheQueue = fTheQueue->link;
182*cf10934eSMichael Lotz #else
183*cf10934eSMichael Lotz 			fTheQueue = fTheQueue->fQueueLink;
184*cf10934eSMichael Lotz #endif
18552a38012Sejakowatz 
18652a38012Sejakowatz 			// Must decrement the count of elements since the front one is being
18752a38012Sejakowatz 			// removed.
18852a38012Sejakowatz 			fMessageCount--;
18952a38012Sejakowatz 
19052a38012Sejakowatz 			// If the new front element is NULL, then that means that the queue
19152a38012Sejakowatz 			// is now empty.  That means that fQueueTail must be set to NULL.
19252a38012Sejakowatz 			if (fTheQueue == NULL) {
19352a38012Sejakowatz 				fQueueTail = NULL;
19452a38012Sejakowatz 			}
19552a38012Sejakowatz 
19652a38012Sejakowatz 			// We have found the message and removed it in this case.  We can
19752a38012Sejakowatz 			// bail out now.  The autolocker will take care of releasing the
19852a38012Sejakowatz 			// lock for us.
19952a38012Sejakowatz 			return;
20052a38012Sejakowatz 		}
20152a38012Sejakowatz 
20252a38012Sejakowatz 		// The message to remove is not the first one, so we need to scan the
20352a38012Sejakowatz 		// queue.  Get a message iterator and set it to the first element.
20452a38012Sejakowatz 		BMessage *messageIter = fTheQueue;
20552a38012Sejakowatz 
20652a38012Sejakowatz 		// While we are not at the end of the list.
20752a38012Sejakowatz 		while (messageIter != NULL) {
20852a38012Sejakowatz 			// If the next message after this (ie second, then third etc) is
20952a38012Sejakowatz 			// the one we are looking for.
210*cf10934eSMichael Lotz #ifndef USING_MESSAGE4
21152a38012Sejakowatz 			if (messageIter->link == message) {
212*cf10934eSMichael Lotz #else
213*cf10934eSMichael Lotz 			if (messageIter->fQueueLink == message) {
214*cf10934eSMichael Lotz #endif
21552a38012Sejakowatz 				// At this point, this is what we have:
21652a38012Sejakowatz 				//    messageIter - the BMessage in the queue just before the
21752a38012Sejakowatz 				//                  match
21852a38012Sejakowatz 				//    messageIter->link - the BMessage which matches message
21952a38012Sejakowatz 				//    message - the same as messageIter->link
22052a38012Sejakowatz 				//    message->link - the element after the match
22152a38012Sejakowatz 				//
22252a38012Sejakowatz 				// The next step is to link the BMessage just before the match
22352a38012Sejakowatz 				// to the one just after the match.  This removes the match from
22452a38012Sejakowatz 				// the queue.
225*cf10934eSMichael Lotz #ifndef USING_MESSAGE4
22652a38012Sejakowatz 				messageIter->link = message->link;
227*cf10934eSMichael Lotz #else
228*cf10934eSMichael Lotz 				messageIter->fQueueLink = message->fQueueLink;
229*cf10934eSMichael Lotz #endif
23052a38012Sejakowatz 
23152a38012Sejakowatz 				// One less element on the queue.
23252a38012Sejakowatz 				fMessageCount--;
23352a38012Sejakowatz 
23452a38012Sejakowatz 				// If there is no BMessage after the match is the
235*cf10934eSMichael Lotz #ifndef USING_MESSAGE4
23652a38012Sejakowatz 				if (message->link == NULL) {
237*cf10934eSMichael Lotz #else
238*cf10934eSMichael Lotz 				if (message->fQueueLink == NULL) {
239*cf10934eSMichael Lotz #endif
24052a38012Sejakowatz 					// That means that we just removed the last element from the
24152a38012Sejakowatz 					// queue.  The new last element then must be messageIter.
24252a38012Sejakowatz 					fQueueTail = messageIter;
24352a38012Sejakowatz 				}
24452a38012Sejakowatz 
24552a38012Sejakowatz 				// We can return now because we have a match and removed it.
24652a38012Sejakowatz 				return;
24752a38012Sejakowatz 			}
24852a38012Sejakowatz 
24952a38012Sejakowatz 			// No match yet, go to the next element in the list.
250*cf10934eSMichael Lotz #ifndef USING_MESSAGE4
25152a38012Sejakowatz 			messageIter = messageIter->link;
252*cf10934eSMichael Lotz #else
253*cf10934eSMichael Lotz 			messageIter = messageIter->fQueueLink;
254*cf10934eSMichael Lotz #endif
25552a38012Sejakowatz 		}
25652a38012Sejakowatz 	}
25752a38012Sejakowatz }
25852a38012Sejakowatz 
25952a38012Sejakowatz 
26052a38012Sejakowatz /*
26152a38012Sejakowatz  *  Method: BMessageQueue::CountMessages()
26252a38012Sejakowatz  *   Descr: This method just returns the number of BMessages on the queue.
26352a38012Sejakowatz  */
26452a38012Sejakowatz int32
26552a38012Sejakowatz BMessageQueue::CountMessages(void) const
26652a38012Sejakowatz {
26752a38012Sejakowatz     return fMessageCount;
26852a38012Sejakowatz }
26952a38012Sejakowatz 
27052a38012Sejakowatz 
27152a38012Sejakowatz /*
27252a38012Sejakowatz  *  Method: BMessageQueue::IsEmpty()
27352a38012Sejakowatz  *   Descr: This method just returns true if there are no BMessages on the queue.
27452a38012Sejakowatz  */
27552a38012Sejakowatz bool
27652a38012Sejakowatz BMessageQueue::IsEmpty(void) const
27752a38012Sejakowatz {
27852a38012Sejakowatz     return (fMessageCount == 0);
27952a38012Sejakowatz }
28052a38012Sejakowatz 
28152a38012Sejakowatz 
28252a38012Sejakowatz /*
28352a38012Sejakowatz  *  Method: BMessageQueue::FindMessage()
28452a38012Sejakowatz  *   Descr: This method searches the queue for the index'th BMessage.  The first
28552a38012Sejakowatz  *          BMessage is at index 0, the second at index 1 etc.  The BMessage
28652a38012Sejakowatz  *          is returned if it is found.  If no BMessage exists at that index
28752a38012Sejakowatz  *          (ie the queue is not that long or the index is invalid) NULL is
28852a38012Sejakowatz  *          returned.
28952a38012Sejakowatz  *
29052a38012Sejakowatz  *          This method does not lock the BMessageQueue so there is risk that
29152a38012Sejakowatz  *          the queue could change in the course of the search.  Be's
29252a38012Sejakowatz  *          implementation must do the same, unless they do some funky casting.
29352a38012Sejakowatz  *          The method is declared const which means it cannot modify the data
29452a38012Sejakowatz  *          members.  Because it cannot modify the data members, it cannot
29552a38012Sejakowatz  *          acquire a lock.  So unless they are casting away the const-ness
29652a38012Sejakowatz  *          of the this pointer, this member in Be's implementation does no
29752a38012Sejakowatz  *          locking either.
29852a38012Sejakowatz  */
29952a38012Sejakowatz BMessage *
30052a38012Sejakowatz BMessageQueue::FindMessage(int32 index) const
30152a38012Sejakowatz {
30252a38012Sejakowatz 	// If the index is negative or larger than the number of messages on the
30352a38012Sejakowatz 	// queue.
30452a38012Sejakowatz 	if ((index < 0) || (index >= fMessageCount)) {
30552a38012Sejakowatz 		// No match is possible, bail out now.
30652a38012Sejakowatz 		return NULL;
30752a38012Sejakowatz 	}
30852a38012Sejakowatz 
30952a38012Sejakowatz 	// Get a message iterator and initialize it to the start of the queue.
31052a38012Sejakowatz 	BMessage *messageIter = fTheQueue;
31152a38012Sejakowatz 
31252a38012Sejakowatz 	// While this is not the end of the queue.
31352a38012Sejakowatz 	while (messageIter != NULL) {
31452a38012Sejakowatz 		// If the index reaches zero, then we have found a match.
31552a38012Sejakowatz 		if (index == 0) {
31652a38012Sejakowatz 			// Because this is a match, break out of the while loop so we can
31752a38012Sejakowatz 			// return the message pointed to messageIter.
31852a38012Sejakowatz 			break;
31952a38012Sejakowatz 		}
32052a38012Sejakowatz 
32152a38012Sejakowatz 		// No match yet, decrement the index.  We will have a match once index
32252a38012Sejakowatz 		// reaches zero.
32352a38012Sejakowatz 		index--;
32452a38012Sejakowatz 		// Increment the messageIter to the next BMessage on the queue.
325*cf10934eSMichael Lotz #ifndef USING_MESSAGE4
32652a38012Sejakowatz 		messageIter = messageIter->link;
327*cf10934eSMichael Lotz #else
328*cf10934eSMichael Lotz 		messageIter = messageIter->fQueueLink;
329*cf10934eSMichael Lotz #endif
33052a38012Sejakowatz 	}
33152a38012Sejakowatz 
33252a38012Sejakowatz 	// If no match was found, messageIter will be NULL since that is the only
33352a38012Sejakowatz 	// way out of the loop.  If a match was found, the messageIter will point
33452a38012Sejakowatz 	// to that match.
33552a38012Sejakowatz     return messageIter;
33652a38012Sejakowatz }
33752a38012Sejakowatz 
33852a38012Sejakowatz 
33952a38012Sejakowatz /*
34052a38012Sejakowatz  *  Method: BMessageQueue::FindMessage()
34152a38012Sejakowatz  *   Descr: This method searches the queue for the index'th BMessage that has a
34252a38012Sejakowatz  *          particular what code.  The first BMessage with that what value is at
34352a38012Sejakowatz  *          index 0, the second at index 1 etc.  The BMessage is returned if it
34452a38012Sejakowatz  *          is found.  If no matching BMessage exists at that index NULL is
34552a38012Sejakowatz  *          returned.
34652a38012Sejakowatz  *
34752a38012Sejakowatz  *          This method does not lock the BMessageQueue so there is risk that
34852a38012Sejakowatz  *          the queue could change in the course of the search.  Be's
34952a38012Sejakowatz  *          implementation must do the same, unless they do some funky casting.
35052a38012Sejakowatz  *          The method is declared const which means it cannot modify the data
35152a38012Sejakowatz  *          members.  Because it cannot modify the data members, it cannot
35252a38012Sejakowatz  *          acquire a lock.  So unless they are casting away the const-ness
35352a38012Sejakowatz  *          of the this pointer, this member in Be's implementation does no
35452a38012Sejakowatz  *          locking either.
35552a38012Sejakowatz  */
35652a38012Sejakowatz BMessage *
35752a38012Sejakowatz BMessageQueue::FindMessage(uint32 what,
35852a38012Sejakowatz                            int32 index) const
35952a38012Sejakowatz {
36052a38012Sejakowatz 	// If the index is negative or larger than the number of messages on the
36152a38012Sejakowatz 	// queue.
36252a38012Sejakowatz 	if ((index < 0) || (index >= fMessageCount)) {
36352a38012Sejakowatz 		// No match is possible, bail out now.
36452a38012Sejakowatz 		return NULL;
36552a38012Sejakowatz 	}
36652a38012Sejakowatz 
36752a38012Sejakowatz 	// Get a message iterator and initialize it to the start of the queue.
36852a38012Sejakowatz 	BMessage *messageIter = fTheQueue;
36952a38012Sejakowatz 
37052a38012Sejakowatz 	// While this is not the end of the queue.
37152a38012Sejakowatz 	while (messageIter != NULL) {
37252a38012Sejakowatz 		// If the messageIter points to a BMessage with the what code we are
37352a38012Sejakowatz 		// looking for.
37452a38012Sejakowatz 		if (messageIter->what == what) {
37552a38012Sejakowatz 			// If the index reaches zero, then we have found a match.
37652a38012Sejakowatz 			if (index == 0) {
37752a38012Sejakowatz 				// Because this is a match, break out of the while loop so we can
37852a38012Sejakowatz 				// return the message pointed to messageIter.
37952a38012Sejakowatz 				break;
38052a38012Sejakowatz 			}
38152a38012Sejakowatz 			// No match yet, decrement the index.  We will have a match once index
38252a38012Sejakowatz 			// reaches zero.
38352a38012Sejakowatz 			index--;
38452a38012Sejakowatz 		}
38552a38012Sejakowatz 		// Increment the messageIter to the next BMessage on the queue.
386*cf10934eSMichael Lotz #ifndef USING_MESSAGE4
38752a38012Sejakowatz 		messageIter = messageIter->link;
388*cf10934eSMichael Lotz #else
389*cf10934eSMichael Lotz 		messageIter = messageIter->fQueueLink;
390*cf10934eSMichael Lotz #endif
39152a38012Sejakowatz 	}
39252a38012Sejakowatz 
39352a38012Sejakowatz 	// If no match was found, messageIter will be NULL since that is the only
39452a38012Sejakowatz 	// way out of the loop.  If a match was found, the messageIter will point
39552a38012Sejakowatz 	// to that match.
39652a38012Sejakowatz     return messageIter;
39752a38012Sejakowatz }
39852a38012Sejakowatz 
39952a38012Sejakowatz 
40052a38012Sejakowatz /*
40152a38012Sejakowatz  *  Method: BMessageQueue::Lock()
40252a38012Sejakowatz  *   Descr: This member just locks the BMessageQueue so no other thread can acquire
40352a38012Sejakowatz  *          the lock nor make changes to the queue through members like
40452a38012Sejakowatz  *          AddMessage(), RemoveMessage(), NextMessage() or ~BMessageQueue().
40552a38012Sejakowatz  */
40652a38012Sejakowatz bool
40752a38012Sejakowatz BMessageQueue::Lock(void)
40852a38012Sejakowatz {
40952a38012Sejakowatz     return fLocker.Lock();
41052a38012Sejakowatz }
41152a38012Sejakowatz 
41252a38012Sejakowatz 
41352a38012Sejakowatz /*
41452a38012Sejakowatz  *  Method: BMessageQueue::Unlock()
41552a38012Sejakowatz  *   Descr: This member releases the lock which was acquired by Lock().
41652a38012Sejakowatz  */
41752a38012Sejakowatz void
41852a38012Sejakowatz BMessageQueue::Unlock(void)
41952a38012Sejakowatz {
42052a38012Sejakowatz 	fLocker.Unlock();
42152a38012Sejakowatz }
42252a38012Sejakowatz 
42352a38012Sejakowatz 
42452a38012Sejakowatz /*
42552a38012Sejakowatz  *  Method: BMessageQueue::IsLocked()
42652a38012Sejakowatz  *   Descr: This member returns whether or not the queue is locked
42752a38012Sejakowatz  */
42852a38012Sejakowatz bool
42952a38012Sejakowatz BMessageQueue::IsLocked(void)
43052a38012Sejakowatz {
43152a38012Sejakowatz 	return fLocker.IsLocked();
43252a38012Sejakowatz }
43352a38012Sejakowatz 
43452a38012Sejakowatz 
43552a38012Sejakowatz /*
43652a38012Sejakowatz  *  Method: BMessageQueue::NextMessage()
43752a38012Sejakowatz  *   Descr: This member removes the first BMessage on the queue and returns
43852a38012Sejakowatz  *          it to the caller.  If the queue is empty, NULL is returned.
43952a38012Sejakowatz  */
44052a38012Sejakowatz BMessage *
44152a38012Sejakowatz BMessageQueue::NextMessage(void)
44252a38012Sejakowatz {
44352a38012Sejakowatz 	// By default, we will assume that no BMessage is on the queue.
44452a38012Sejakowatz 	BMessage *result = NULL;
44552a38012Sejakowatz 	BAutolock theAutoLocker(fLocker);
44652a38012Sejakowatz 
44752a38012Sejakowatz 	// The Be implementation does not seem to check that the lock acquisition
44852a38012Sejakowatz 	// was successful.  This will specifically cause problems when the
44952a38012Sejakowatz 	// message queue is deleted.  On delete, any thread waiting for the lock
45052a38012Sejakowatz 	// will be notified that the lock failed.  Be's implementation, because
45152a38012Sejakowatz 	// they do not check proceeds with the operation, potentially corrupting
45252a38012Sejakowatz 	// memory.  This implementation is different, but I can't imagine that
45352a38012Sejakowatz 	// Be's implementation is worth emulating.
45452a38012Sejakowatz 	//
45552a38012Sejakowatz 	if (theAutoLocker.IsLocked()) {
45652a38012Sejakowatz 		// Store the first BMessage in the queue in result.
45752a38012Sejakowatz 		result = fTheQueue;
45852a38012Sejakowatz 
45952a38012Sejakowatz 		// If the queue is not empty.
46052a38012Sejakowatz 		if (fTheQueue != NULL) {
46152a38012Sejakowatz 			// Decrement the message count since we are removing an element.
46252a38012Sejakowatz 			fMessageCount--;
46352a38012Sejakowatz 			// The new front of the list is moved forward thereby removing the
46452a38012Sejakowatz 			// first element from the queue.
465*cf10934eSMichael Lotz #ifndef USING_MESSAGE4
46652a38012Sejakowatz 			fTheQueue = fTheQueue->link;
467*cf10934eSMichael Lotz #else
468*cf10934eSMichael Lotz 			fTheQueue = fTheQueue->fQueueLink;
469*cf10934eSMichael Lotz #endif
47052a38012Sejakowatz 			// If the queue is empty after removing the front element.
47152a38012Sejakowatz 			if (fTheQueue == NULL) {
47252a38012Sejakowatz 				// We need to set the tail of the queue to NULL since the queue
47352a38012Sejakowatz 				// is now empty.
47452a38012Sejakowatz 				fQueueTail = NULL;
47552a38012Sejakowatz 			}
47652a38012Sejakowatz 		}
47752a38012Sejakowatz 	}
47852a38012Sejakowatz     return result;
47952a38012Sejakowatz }
48052a38012Sejakowatz 
48152a38012Sejakowatz 
48252a38012Sejakowatz void
48352a38012Sejakowatz BMessageQueue::_ReservedMessageQueue1(void)
48452a38012Sejakowatz {
48552a38012Sejakowatz }
48652a38012Sejakowatz 
48752a38012Sejakowatz 
48852a38012Sejakowatz void
48952a38012Sejakowatz BMessageQueue::_ReservedMessageQueue2(void)
49052a38012Sejakowatz {
49152a38012Sejakowatz }
49252a38012Sejakowatz 
49352a38012Sejakowatz 
49452a38012Sejakowatz void
49552a38012Sejakowatz BMessageQueue::_ReservedMessageQueue3(void)
49652a38012Sejakowatz {
49752a38012Sejakowatz }
49852a38012Sejakowatz 
49952a38012Sejakowatz #ifdef USE_OPENBEOS_NAMESPACE
50052a38012Sejakowatz }
50152a38012Sejakowatz #endif
502