1 //---------------------------------------------------------------------- 2 // This software is part of the Haiku distribution and is covered 3 // by the MIT License. 4 //--------------------------------------------------------------------- 5 6 #include <Message.h> 7 8 #include "PriorityMessageQueue.h" 9 10 // MessageInfo 11 class PriorityMessageQueue::MessageInfo { 12 public: 13 MessageInfo(BMessage *message, int32 priority) 14 : fMessage(message), 15 fPriority(priority) 16 { 17 } 18 19 BMessage *Message() const { return fMessage; } 20 int32 Priority() const { return fPriority; } 21 22 private: 23 BMessage *fMessage; 24 int32 fPriority; 25 }; 26 27 28 // constructor 29 PriorityMessageQueue::PriorityMessageQueue() 30 : fLock(), 31 fMessages(20, true) 32 { 33 } 34 35 // destructor 36 PriorityMessageQueue::~PriorityMessageQueue() 37 { 38 // delete the messages 39 for (int32 i = 0; MessageInfo *info = fMessages.ItemAt(i); i++) 40 delete info->Message(); 41 // the infos are deleted automatically 42 } 43 44 // Lock 45 bool 46 PriorityMessageQueue::Lock() 47 { 48 return fLock.Lock(); 49 } 50 51 // Unlock 52 void 53 PriorityMessageQueue::Unlock() 54 { 55 fLock.Unlock(); 56 } 57 58 // PushMessage 59 bool 60 PriorityMessageQueue::PushMessage(BMessage *message, int32 priority) 61 { 62 bool result = (message); 63 if (result) 64 result = Lock(); 65 if (result) { 66 if (MessageInfo *info = new MessageInfo(message, priority)) { 67 // find the insertion index 68 int32 index = _FindInsertionIndex(priority); 69 if (!fMessages.AddItem(info, index)) { 70 result = false; 71 delete info; 72 } 73 } else // no memory 74 result = false; 75 Unlock(); 76 } 77 return result; 78 } 79 80 // PopMessage 81 BMessage * 82 PriorityMessageQueue::PopMessage() 83 { 84 BMessage *result = NULL; 85 if (Lock()) { 86 if (MessageInfo *info = fMessages.RemoveItemAt(0)) { 87 result = info->Message(); 88 delete info; 89 } 90 Unlock(); 91 } 92 return result; 93 } 94 95 // CountMessages 96 int32 97 PriorityMessageQueue::CountMessages() const 98 { 99 int32 result = 0; 100 if (fLock.Lock()) { 101 result = fMessages.CountItems(); 102 fLock.Unlock(); 103 } 104 return result; 105 } 106 107 // IsEmpty 108 bool 109 PriorityMessageQueue::IsEmpty() const 110 { 111 return (CountMessages() == 0); 112 } 113 114 // _FindInsertionIndex 115 int32 116 PriorityMessageQueue::_FindInsertionIndex(int32 priority) 117 { 118 int32 lower = 0; 119 int32 upper = fMessages.CountItems(); 120 while (lower < upper) { 121 int32 mid = (lower + upper) / 2; 122 MessageInfo *info = fMessages.ItemAt(mid); 123 if (info->Priority() >= priority) 124 lower = mid + 1; 125 else 126 upper = mid; 127 } 128 return lower; 129 } 130 131