One of the foundations of the Haiku API is the messaging system. This framework is the basis for the efficient multithreaded Haiku applications, because it solves one of the fundamental issues of multithreading: it allows you to easily and securely communicate between threads. The framework allows inter-application messaging as well as intra-application messaging, and it will always use the most effective mechanism for the communication automatically.
This page will introduce you to the subject of messaging. It is meant as a broad overview to the classes, rather than a tutorial. If you are looking for effective messaging techniques or a tutorial on messaging, have a look at the developer section of the Haiku website.
Table of contents
The BMessage class is the class that is in the center of all the messenger operations, because it represents a message. A message is nothing more than an object that contains:
uint32that determines the type of message. Some constants are defined by the Haiku API, for example B_MOUSE_DOWN or B_QUIT_REQUESTED.
BMessage itself is generic, its syntax and semantics are determined by the context. The Haiku API defines several messages and their required data members. Several applications provide a scripting interface with defined message syntax. You can do the same for your application.
Objects of the BLooper type are objects that run message loops. Every object runs in its own thread. The BLooper objects continually check for incoming messages. To process the messages, the looper looks for message handlers that handle the messages within the thread's context. Message handling within a looper is synchronous.
BLooper inherits BHandler, the base class for message handling. However, it is possible to chain additional handlers to the object. For example, if you have an application that understands different networking protocols, and you support extensions that understand the base protocol, these extensions can provide handlers that you can chain in your general message parser thread. See AddHandler() and SetPreferredHandler() for information on handlers.
Messages can be posted to the looper by using the object's PostMessage() method. This method puts the message in the BMessageQueue of the looper. Since PostMessage() is asynchronous, the message might not be handled immediately. See BMessenger for a synchronous implementation.
Loopers can have a generic filter that discards messages based on user-definable characteristics. The BMessageFilter class provides the foundation for the qualifying of messages. See AddCommonFilterList() and SetCommonFilterList() for more information.
To get the most out of the functionality of BLooper, it is usually subclassed to create a self-contained event 'machine'. Most of the time, these subclasses also perform the message handling, which is possible due to the fact that it is also a subclass of BHandler.
In the Haiku API, there are two major classes that inherit BLooper: the base application class, BApplication, and the window class, BWindow. Because they inherit BLooper, each application and each window has its own message loop. This makes every window quick and responsive. To keep your applications running smoothly, it is advisable to make sure that event handling that requires more processing power, is done within its own BLooper context. Networking usually qualifies as a candidate for its own thread.
Objects of the BHandler type are associated to BLoopers. When they are created, they should be passed to the BLooper::AddHandler() method of the looper they want to handle messages for. They can then either be set as preferred handlers (by chaining them with BLooper::SetPreferredHandler()), or they can be added to other BHandlers with the SetNextHandler() method.
The magic of the class happens in the MessageReceived() method. In your subclasses you override this method, to check the incoming BMessage. Usually, you check the
what member of the message in a switch statement. If your handler cannot handle the object, it will pass the message on to the parent class.
BMessenger objects can send messages to both local and remote targets. For local targets, a BMessenger provides an advantage over directly calling the BLooper::PostMessage() method: some variants of the BMessenger::SendMessage() methods allow for synchronous replies. So, the call will actually verify the handling thread processes the message, and reply to the sender.
The other feature of BMessenger is that it is able to be constructed with the signature of another application as argument. This allows the messenger to pass messages to other applications. It facilitates inter-application communication.
There are several convenience classes supplied with the application kit, which can make your life easier in some specific cases.