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