xref: /haiku/src/servers/registrar/PriorityMessageQueue.cpp (revision b28ed9e04a771e5de38be68abd08148c0bbafc56)
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