1 /*
2 * Copyright 2001-2014 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Unknown? Eric?
7 * Axel Dörfler, axeld@pinc-software.de
8 */
9
10
11 // Queue for holding BMessages
12
13
14 #include <MessageQueue.h>
15 #include <Autolock.h>
16 #include <Message.h>
17
18
BMessageQueue()19 BMessageQueue::BMessageQueue()
20 :
21 fHead(NULL),
22 fTail(NULL),
23 fMessageCount(0),
24 fLock("BMessageQueue Lock")
25 {
26 }
27
28
~BMessageQueue()29 BMessageQueue::~BMessageQueue()
30 {
31 if (!Lock())
32 return;
33
34 BMessage* message = fHead;
35 while (message != NULL) {
36 BMessage* next = message->fQueueLink;
37
38 delete message;
39 message = next;
40 }
41 }
42
43
44 void
AddMessage(BMessage * message)45 BMessageQueue::AddMessage(BMessage* message)
46 {
47 if (message == NULL)
48 return;
49
50 BAutolock _(fLock);
51 if (!IsLocked())
52 return;
53
54 // The message passed in will be the last message on the queue so its
55 // link member should be set to null.
56 message->fQueueLink = NULL;
57
58 fMessageCount++;
59
60 if (fTail == NULL) {
61 // there are no messages in the queue yet
62 fHead = fTail = message;
63 } else {
64 // just add it after the tail
65 fTail->fQueueLink = message;
66 fTail = message;
67 }
68 }
69
70
71 void
RemoveMessage(BMessage * message)72 BMessageQueue::RemoveMessage(BMessage* message)
73 {
74 if (message == NULL)
75 return;
76
77 BAutolock _(fLock);
78 if (!IsLocked())
79 return;
80
81 BMessage* last = NULL;
82 for (BMessage* entry = fHead; entry != NULL; entry = entry->fQueueLink) {
83 if (entry == message) {
84 // remove this one
85 if (entry == fHead)
86 fHead = entry->fQueueLink;
87 else
88 last->fQueueLink = entry->fQueueLink;
89
90 if (entry == fTail)
91 fTail = last;
92
93 fMessageCount--;
94 return;
95 }
96 last = entry;
97 }
98 }
99
100
101 int32
CountMessages() const102 BMessageQueue::CountMessages() const
103 {
104 return fMessageCount;
105 }
106
107
108 bool
IsEmpty() const109 BMessageQueue::IsEmpty() const
110 {
111 return fMessageCount == 0;
112 }
113
114
115 BMessage*
FindMessage(int32 index) const116 BMessageQueue::FindMessage(int32 index) const
117 {
118 BAutolock _(fLock);
119 if (!IsLocked())
120 return NULL;
121
122 if (index < 0 || index >= fMessageCount)
123 return NULL;
124
125 for (BMessage* message = fHead; message != NULL; message = message->fQueueLink) {
126 // If the index reaches zero, then we have found a match.
127 if (index == 0)
128 return message;
129
130 index--;
131 }
132
133 return NULL;
134 }
135
136
137 BMessage*
FindMessage(uint32 what,int32 index) const138 BMessageQueue::FindMessage(uint32 what, int32 index) const
139 {
140 BAutolock _(fLock);
141 if (!IsLocked())
142 return NULL;
143
144 if (index < 0 || index >= fMessageCount)
145 return NULL;
146
147 for (BMessage* message = fHead; message != NULL; message = message->fQueueLink) {
148 if (message->what == what) {
149 // If the index reaches zero, then we have found a match.
150 if (index == 0)
151 return message;
152
153 index--;
154 }
155 }
156
157 return NULL;
158 }
159
160
161 bool
Lock()162 BMessageQueue::Lock()
163 {
164 return fLock.Lock();
165 }
166
167
168 void
Unlock()169 BMessageQueue::Unlock()
170 {
171 fLock.Unlock();
172 }
173
174
175 bool
IsLocked() const176 BMessageQueue::IsLocked() const
177 {
178 return fLock.IsLocked();
179 }
180
181
182 BMessage*
NextMessage()183 BMessageQueue::NextMessage()
184 {
185 BAutolock _(fLock);
186 if (!IsLocked())
187 return NULL;
188
189 // remove the head of the queue, if any, and return it
190
191 BMessage* head = fHead;
192 if (head == NULL)
193 return NULL;
194
195 fMessageCount--;
196 fHead = head->fQueueLink;
197
198 if (fHead == NULL) {
199 // If the queue is empty after removing the front element,
200 // we need to set the tail of the queue to NULL since the queue
201 // is now empty.
202 fTail = NULL;
203 }
204
205 return head;
206 }
207
208
209 bool
IsNextMessage(const BMessage * message) const210 BMessageQueue::IsNextMessage(const BMessage* message) const
211 {
212 BAutolock _(fLock);
213 return fHead == message;
214 }
215
216
217 // This method is only here for R5 binary compatibility!
218 // It should be dropped as soon as possible (it misses the const qualifier).
219 bool
IsLocked()220 BMessageQueue::IsLocked()
221 {
222 return fLock.IsLocked();
223 }
224
225
_ReservedMessageQueue1()226 void BMessageQueue::_ReservedMessageQueue1() {}
_ReservedMessageQueue2()227 void BMessageQueue::_ReservedMessageQueue2() {}
_ReservedMessageQueue3()228 void BMessageQueue::_ReservedMessageQueue3() {}
229
230