BMessage

Introduction

In Haiku OS, BMessage is a fundamental class that enables communication between different parts of the operating system. It provides a flexible and efficient way for processes to exchange data and synchronize their activities. In this article, we'll explore the BMessage class in Haiku OS, how it works, and how it is used to implement messaging passing.

What is BMessage?

BMessage is a class in Haiku OS that represents a message that can be sent from one process to another. It provides a flexible and extensible mechanism for passing data between different parts of the operating system.

  • BMessage acts as a container that can be sent and received, providing a flexible and efficient mechanism for inter-process communication.
  • It is the center of all the messenger operations, because it represents a message.

This BMessage class is defined at location:

  • Header file: headers/os/app/Message.h
  • Source file: src/kits/app/Message.cpp

Official BMessage documentation is available at: https://www.haiku-os.org/docs/api/classBMessage.html

A message is nothing more than an object that contains:

  • The what member, an unit32 that determines the type of message. Some constants are defined by the Haiku API, for example B_MOUSE_DOWN or B_QUIT_REQUESTED.
  • Zero or more data objects. BMessage is a powerful data container that keeps track of different sorts of data. BMessage provides many convenient Add*() methods, for example BMessage::AddBool(). With the corresponding Find*() method (in this example, FindBool() ) you can retrieve the data

Structure of BMessage:

ABMessage consists of two main elements: the what identifier and the data members.

While the "what" identifier can be directly manipulated, the data members can be modified using methods such as AddData(), FindData(), and ReplaceData().

BMessage::what

A 4-byte constant that determines the type of message.

You can directly manipulate this data member.
It is public data member, You can always set and examine the "what" value directly, you don't need to call a function.

Meta Data Handling:

Apart from data storage, BMessage also stores meta data about the message, including its origin and purpose. Some of the important meta data handling methods provided by BMessage are:

  • IsReply(): Checks if the message is a reply.
  • IsSourceRemote(): Determines if the message came from a remote source.
  • IsSourceWaiting(): Checks if a reply is expected.
  • Previous(): Retrieves the message to which the current message is a reply.

Usage of BMessage:

Mostly, messages are used to pass information between the the objects in your application, but because messages are such flexible data containers, they are also often used for other data storage purposes. Many applications store their settings as messages. Because messages can be flattened to data streams (such as files), they provide an easy but powerful tool for data storage.

Method Classification:

Methods provided by the BMessage class can be broadly classified into the following areas:

1 Adding, Finding, Replacing and Removing Data.

Methods for manipulating data members of the message.

AddData(const char* name, type_code type, const void* data, ssize_t numBytes, bool isFixedSize = false)
AddData(const char* name, type_code type, int32 count, const void* data, bool isFixedSize = false)
AddFlat(const char* name, const BFlattenable* object)
AddFlat(const char* name, const BMessage* message)
AddMessage(const char* name, const BMessage* message)
AddRect(const char* name, BRect rect)
AddPoint(const char* name, BPoint point)
AddString(const char* name, const char* string)
AddString(const char* name, const BString* string)
AddString(const char* name, const char* string, int32 length)
AddInt8(const char* name, int8 number)
AddInt16(const char* name, int16 number)
AddInt32(const char* name, int32 number)
AddInt64(const char* name, int64 number)
AddFloat(const char* name, float number)
AddDouble(const char* name, double number)
AddBool(const char* name, bool boolean)
AddPointer(const char* name, const void* pointer)
AddMessenger(const char* name, const BMessenger* messenger)
AddRef(const char* name, const entry_ref* ref)
AddRef(const char* name, const entry_ref& ref)
AddSpecifier(const char* name, int32 index, int32 what, const BMessage* specifier)
FindData(const char* name, type_code type, ssize_t* numBytes) const
FindData(const char* name, type_code type, ssize_t* numBytes, int32* count) const
FindFlat(const char* name, const BFlattenable** object) const
FindFlat(const char* name, const BMessage** message) const
FindMessage(const char* name, int32 index, const BMessage** message) const
FindRect(const char* name, BRect* rect) const
FindPoint(const char* name, BPoint* point) const
FindString(const char* name, const char** string) const
FindString(const char* name, BString* string) const
FindInt8(const char* name, int8* number) const
FindInt16(const char* name, int16* number) const
FindInt32(const char* name, int32* number) const
FindInt64(const char* name, int64* number) const
FindFloat(const char* name, float* number) const
FindDouble(const char* name, double* number) const
FindBool(const char* name, bool* boolean) const
FindPointer(const char* name, void** pointer) const
FindMessenger(const char* name, BMessenger* messenger) const
FindRef(const char* name, entry_ref* ref) const
FindSpecifier(const char* name, int32 index, int32* what, const BMessage** specifier) const
ReplaceData(const char* name, type_code type, const void* data, ssize_t numBytes, bool isFixedSize = false, int32 index = 0)
ReplaceData(const char* name, type_code type, int32 count, const void* data, bool isFixedSize = false, int32 index = 0)
ReplaceFlat(const char* name, const BFlattenable* object, int32 index = 0)
ReplaceMessage(const char* name, const BMessage* message, int32 index = 0)
ReplaceRect(const char* name, BRect rect, int32 index = 0)
ReplacePoint(const char* name, BPoint point, int32 index = 0)
ReplaceString(const char* name, const char* string, int32 index = 0)
ReplaceString(const char* name, const BString* string, int32 index = 0)
ReplaceInt8(const char* name, int8 number, int32 index = 0)
ReplaceInt16(const char* name, int16 number, int32 index = 0)
ReplaceInt32(const char* name, int32 number, int32 index = 0)
ReplaceInt64(const char* name, int64 number, int32 index = 0)
ReplaceFloat(const char* name, float number, int32 index = 0)
ReplaceDouble(const char* name, double number, int32 index = 0)
ReplaceBool(const char* name, bool boolean, int32 index = 0)
ReplacePointer(const char* name, const void* pointer, int32 index = 0)
ReplaceMessenger(const char* name, const BMessenger* messenger, int32 index = 0)
ReplaceRef(const char* name, const entry_ref* ref, int32 index = 0)
ReplaceSpecifier(const char* name, int32 index, int32 what, const BMessage* specifier)

2 Statistics and Miscellaneous information.

Methods for retrieving information about the message.

Archive(BMessage* into, bool deep = true) const
Unflatten(const void* data, ssize_t numBytes)
PrintToStream() const
GetInfo(int32* what, int32* specifier, team_id* source, bigtime_t* when, uint32* flags) const
WasDelivered(bool* preferred = NULL) const
IsSystem() const
IsReply() const
IsReplyTo(const BMessage* replyTo) const
WasSourceTeam(team_id team) const
IsSourceRemote() const
IsSourceWaiting() const
WasTransferred() const
Previous(BMessage* message) const
GetReply(BMessage* reply) const
ReturnAddress(BMessage* address) const
ReturnToSender(status_t returnCode)

3 Delivery information.

Methods for handling message delivery.

SendReply(const BMessage* reply, status_t status)
SendReply(uint32 command)
SendReply(BMessage& reply)
SendReply(uint32 command, const BMessage& reply)
SendReply(const BMessage* reply, status_t status, bigtime_t timeout)
SendReply(uint32 command, const BMessage* reply, status_t status, bigtime_t timeout)

4 Utilities to reply to messages.

Methods for replying to received messages.

FindMessenger(const char* name, team_id team, BMessenger* messenger) const
FindRef(const char* name, team_id team, entry_ref* ref) const
HasSpecifiers() const
FindSpecifier(const char* name, int32 index, int32* what, const BMessage** specifier, team_id team = -1) const
RemoveData(const char* name, int32 index = 0)
RemoveName(const char* name, int32 index = 0)
RemoveName(const char* name, int32 from, int32 to)
Rename(const char* old_name, const char* new_name, int32 index = 0)

Example Usage of BMessage:

// Creating a message
BMessage message(MSG_HELLO);
message.AddString("name", "Haiku");

// Sending the message
BMessenger messenger("target_application");
messenger.SendMessage(&message);

Basic Usage:

1 Creating a Message:

#include <Message.h>

// Create a message
BMessage message;

2 Adding Data to the Message:

  • You can add various types of data to the message using AddXXX() methods (e.g., AddString(), AddInt32(), AddFloat()).
// Add data to the message
message.AddString("name", "John");
message.AddInt32("age", 30);
   +-----------------------------------------------------+
   |                                                     |
   |                    BMessage                         |
   |                                                     |
   |  +--------------+       +--------------+            |
   |  |   Field 1    |       |   Field 2    |            |
   |  | (e.g., name) |       | (e.g., age)  |            |
   |  +--------------+       +--------------+            |
   |  |   "John"     |       |     30       |            |
   |  +--------------+       +--------------+            |
   |        ...                     ...                  |
   +-----------------------------------------------------+

3 Retrieving Data from the Message:

  • You retrieve data from the message using FindXX() methods (e.g., FindString(), FindInt32(), FindFloat()).
// Retrieve data from the message
const char* name;
int32 age;
if (message.FindString("name", &name) == B_OK) {
    printf("Name: %s\n", name);
}
if (message.FindInt32("age", &age) == B_OK) {
    printf("Age: %d\n", age);
}

4 Sending the Message:

// Send the message to a BHandler or BLooper
handler->MessageReceived(&message);