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