xref: /haiku/src/kits/app/MessageQueue.cpp (revision be902ac4db5c9d0be72f6d54aa67b66e3dcc7eca)
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