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