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
18BMessageQueue::BMessageQueue()
19	:
20	fHead(NULL),
21 	fTail(NULL),
22 	fMessageCount(0),
23 	fLock("BMessageQueue Lock")
24{
25}
26
27
28BMessageQueue::~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
43void
44BMessageQueue::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
70void
71BMessageQueue::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
100int32
101BMessageQueue::CountMessages() const
102{
103    return fMessageCount;
104}
105
106
107bool
108BMessageQueue::IsEmpty() const
109{
110    return fMessageCount == 0;
111}
112
113
114BMessage *
115BMessageQueue::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
136BMessage *
137BMessageQueue::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
160bool
161BMessageQueue::Lock()
162{
163    return fLock.Lock();
164}
165
166
167void
168BMessageQueue::Unlock()
169{
170	fLock.Unlock();
171}
172
173
174bool
175BMessageQueue::IsLocked() const
176{
177	return fLock.IsLocked();
178}
179
180
181BMessage *
182BMessageQueue::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
208bool
209BMessageQueue::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*/
220bool
221BMessageQueue::IsLocked()
222{
223	return fLock.IsLocked();
224}
225
226
227void BMessageQueue::_ReservedMessageQueue1() {}
228void BMessageQueue::_ReservedMessageQueue2() {}
229void BMessageQueue::_ReservedMessageQueue3() {}
230
231