xref: /haiku/docs/develop/kits/app/usecases/BMessageQueueUseCases.html (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
1<HTML>
2<!-- $Id: BMessageQueueUseCases.html 10 2002-07-09 12:24:59Z ejakowatz $ -->
3<HEAD>
4<TITLE>BMessageQueue Use Cases and Implementation Details</TITLE>
5</HEAD>
6
7<BODY BGCOLOR="white" LINK="#000067" VLINK="#000067" ALINK="#0000FF">
8
9<FONT FACE="Verdana,Arial,Helvetica,sans-serif" SIZE="-1">
10
11<H1>BMessageQueue Use Cases and Implementation Details:</H1>
12
13<P>This document describes the BMessageQueue interface and some basics of how it is implemented.
14The document has the following sections:</P>
15
16<OL>
17<LI><A HREF="#interface">BMessageQueue Interface</A></LI>
18<LI><A HREF="#usecases">BMessageQueue Use Cases</A></LI>
19<LI><A HREF="#implement">BMessageQueue Implementation</A></LI>
20</OL>
21
22<A NAME="interface"></A><H2>BMessageQueue Interface:</H2>
23
24<P>The BMessageQueue class is a simple class for managing a queue of BMessages.  The best
25source of information for the BMessageQueue interface can be found
26<A HREF="https://www.haiku-os.org/legacy-docs/bebook/BMessageQueue.html">here in the Be Book</A>.
27</P>
28
29<A NAME="usecases"></A><H2>BMessageQueue Use Cases:</H2>
30
31<P>The following use cases cover the BMessageQueue functionality:</P>
32
33<OL>
34<LI><P><B>Construction:</B> A BMessageQueue does not take any arguments when it is constructed.
35After construction, the queue is empty.</P></LI>
36
37<LI><P><B>Destruction:</B> When a BMessageQueue is deconstructed, all BMessages on the queue are
38deleted.  This implies that all BMessages added to a BMessageQueue must be allocated on the heap
39with the new operation.  The BMessageQueue is locked before performing the delete to ensure
40that the queue doesn't change while it is being deleted.  The lock is never released from the
41destructor to ensure that any AddMessage() or other members blocking for the lock never
42succeed in getting the lock.  They will fail once the BMessageQueue is completely deleted.</P></LI>
43
44<LI><P><B>Add Message 1:</B> When AddMessage() is used to put a BMessage on the queue, the
45BMessageQueue takes ownership of the BMessage.  The BMessage should be created on the heap but
46there is no checking to ensure that has happened.  The BMessageQueue records the order in
47which the BMessages are added to the queue.</P></LI>
48
49<LI><P><B>Add Message 2:</B> No check is performed to see if the BMessage is already part of that
50BMessageQueue or any other when AddMessage() is used to put a BMessage on a queue.  An attempt to
51add a BMessage to a BMessageQueue which already has that same BMessage in it (where equality is
52based on the address of the BMessage) will corrupt the queue.  An attempt to add a BMessage to a
53BMessageQueue when that BMessage is already in another BMessageQueue will corrupt the original
54BMessageQueue.  It is up to the caller of AddMessage() to use RemoveMessage() to prevent
55queue corruption.</P></LI>
56
57<LI><P><B>Add Message 3:</B> BMessage's can be added using AddMessage() from multiple threads
58at the same time with no risk of queue corruption.  Similarly, RemoveMessage() or NextMessage()
59can be executing from another thread while an AddMessage() is started without corrupting the queue.
60An AddMessage() attempt will block if another thread has used the Lock() member to lock the
61BMessageQueue.</P></LI>
62
63<LI><P><B>Remove Message 1:</B> The RemoveMessage() member takes a BMessage pointer.  The
64BMessageQueue is searched for this BMessage pointer.  If that pointer is in the queue, then it
65is removed from the queue.  The BMessage is not deleted (note the BeBook implies it is but in
66fact it is not).  If the BMessage pointer is not on this BMessageQueue, this call has no affect.
67After this call completes successfully, it is as though AddMessage() was never called for
68this BMessage pointer.</P></LI>
69
70<LI><P><B>Remove Message 2:</B> BMessage's can be removed using RemoveMessage() from multiple
71threads at the same time with no risk of queue corruption.  Similarly, AddMessage() or
72NextMessage() can be executing from another thread while a RemoveMessage() is started without
73corrupting the queue.  A RemoveMessage() attempt will block if another thread has used the Lock()
74member to lock the BMessageQueue.</P></LI>
75
76<LI><P><B>Count Messages:</B> The CountMessages() member function returns the number of BMessage's
77in the BMessageQueue.  If there are no messages on the queue (an example of this situation is just
78after construction), the member returns 0.  Note, it is possible for the count to become corrupted
79if the situation in Add Message 2 occurs.</P></LI>
80
81<LI><P><B>Is Empty:</B> The IsEmpty() member function returns true if there are no BMessages on the
82BMessageQueue.  If there are one or more BMessages on the BMessageQueue, it returns false.</P></LI>
83
84<LI><P><B>Find Message 1:</B> The FindMessage() member function is overloaded.  If the member
85function takes a single int32 argument, it is used to return the BMessage on the queue at a
86particular index as indicated by the argument.  The first message is at index 0, the second
87at index 1 etc.  If no message is at that index, NULL is returned.</P></LI>
88
89<LI><P><B>Find Message 2:</B> The other FindMessage() member function takes a single uint32
90argument and an optional int32 argument.  The first mandatory argument specifies the "what" code
91for the BMessage being searched for.  The second optional argument specifies what occurance of
92that "what" code in a BMessage on the queue should be returned.  If the second argument is not
93provided, it is assumed to be 0.  If the second argument is 0, the first BMessage that has the
94what code provided is returned.  If the second argument is 1, the second BMessage that has the
95what code provided is returned, etc.  If no match is found, NULL is returned.</P></LI>
96
97<LI><P><B>Lock 1:</B> The Lock() member function blocks until this thread can acquire exclusive
98access to the BMessageQueue.  Only one thread can hold the lock at any one time.  A thread can
99acquire the Lock() multiple times but release it the same number of times.  While a thread holds
100the lock, other threads will not be able to perform AddMessage(), RemoveMessage() or NextMessage().
101Any threads attempting to do so will block until the BMessageQueue is unlocked.</P></LI>
102
103<LI><P><B>Lock 2:</B> The Lock() member function returns true if the lock has successfully been
104acquired.  It will return false if an unrecoverable error has occurred.  An example of such an
105error would be deleting the BMessageQueue.</P></LI>
106
107<LI><P><B>Unlock:</B> The Unlock() member function releases a lock on the BMessageQueue.  If the
108thread no longer holds any locks on the BMessageQueue, other threads are free to acquire the
109BMessageQueue lock or call member functions like AddMessage(), RemoveMessage(), NextMessage() or
110delete the BMessageQueue.</P></LI>
111
112<LI><P><B>Next Message 1:</B> The NextMessage() member function removes the BMessage which is the
113oldest on the queue.  It returns that BMessage to the caller.  After the call completes, the
114BMessage is no longer on the queue and the next oldest BMessage is at the front of the queue
115(ie next to be returned by NextMessage()).</P></LI>
116
117<LI><P><B>Next Message 2:</B> BMessage's can be removed using NextMessage() from multiple
118threads at the same time with no risk of queue corruption.  Similarly, AddMessage() or
119RemoveMessage() can be executing from another thread while a NextMessage() is started without
120corrupting the queue.  A NextMessage() attempt will block if another thread has used the Lock()
121member to lock the BMessageQueue.</P></LI>
122
123</OL>
124
125<A NAME="implement"></A><H2>BMessageQueue Implementation:</H2>
126
127<P>Internally, the BMessageQueue uses a BLocker to ensure that member functions like AddMessage(),
128RemoveMessage() and NextMessage() do not corrupt the queue when used from multiple threads.  The
129same BLocker is used to implemented the Lock() and Unlock() members.</P>
130
131<P>Testing with a debugger shows that the queue is implemented using a "link" pointer in the
132BMessage class itself.  Each BMessage is also a singly linked list which represents the queue.
133All the BMessageQueue needs is a pointer to the BMessage which starts the list.  For performance
134reasons, it is worth maintaining a pointer to the BMessage at the end of the list and the count
135of the number of elements in the list.  If these are not maintained, adding an element to the
136list will get slower as the number of elements grows and the cost to determine the number of
137elements in the list will be high.</P>
138
139<P>Because the BMessageQueue uses the link pointer which is a private part of the BMessage class,
140the BMessageQueue must be a friend class of BMessage.  Checking the headers, this is in fact the
141case in Be's implementation.  Although friendship in classes can cause some pretty serious long
142term headaches if abused (and I am not convinced that this is an abuse), the OpenBeOS
143implementation will follow the same implementation for now.</P>
144
145
146</BODY>
147</HTML>
148