Derived from: public BObject
Declared in: <app/Messenger.h>
A BMessenger object is an agent for sending messages to a particular destination. Each BMessenger knows about a BLooper object and a specific BHandler for that BLooper. The messages it sends are delivered to the BLooper and--provided they're not system messages--dispatched by the BLooper to the BHandler. The destination objects can belong to the same application as the message sender, but typically are in a remote application. It's more efficient to post a message within the same application than to ask a BMessenger to send it.
BMessenger objects can be transported across application boundaries. You can create one for a particular BLooper/BHandler combination in your application, then pass it by value to a remote application. That application can then use the BMessenger to target the BHandler in your application. This is, in fact, the only way for an application to get a BMessenger that can target a remote object other than a BApplication object.
BMessenger(ulong signature, team_id team = -1) BMessenger(const BHandler *target) BMessenger(const BMessenger &messenger) BMessenger(void)
Initializes the BMessenger so that it can send messages to an application identified by its signature or by its team. The application must be running when the BMessenger is constructed.
If the signature passed is NULL, the application is identified by its team only. If the team specified is -1, as it is by default, the application is identified by its signature only. If both a real signature and a valid team identifier are passed, they must match --the team must be for the application that the signature identifies. If more than one instance of the signature application happens to be running, the team picks out a particular instance as the BMessenger's target. Without a valid team argument, the constructor arbitrarily picks one of the instances.
BMessengers constructed in this way send messages to the main thread of the remote application, where they're received and handled by that application's BApplication object. This type of messenger is needed to initiate communication with another application.
A BMessenger can also be an agent for a target BHandler object. It sends messages to the BLooper associated with the BHandler, and the BLooper dispatches them to the BHandler.
The target BHandler object must be able to tell the BMessenger (through its Looper() function) which BLooper object it's associated with. The BMessenger asks for this information at the time of construction. Therefore, the target must either be a BLooper itself or have been added to a BLooper's list of eligible handlers. < For the BMessenger to remain valid, the target BHandler must retain its affiliation with the same BLooper. >
The purpose of constructing a BMessenger for a local target is to give a remote application access to that object. You can add the BMessenger to a message and send the message to the remote application. That application can then use the BMessenger to target the BHandler in your application.
A BMessenger can also be constructed as a copy of another BMessenger,
BMessenger newOne(anotherMessenger);
or be assigned from another object:
BMessenger newOne = anotherMessenger;
If the constructor can't make a connection to the signature application--possibly because no such application is running--it registers a B_BAD_VALUE error, which the Error() function will return. If passed an invalid team identifier, it registers a B_BAD_TEAM_ID error. If the team and the signature don't match, it registers a B_MISMATCHED_VALUES error. If it can't discover a BLooper from the target BHandler, it registers a B_BAD_HANDLER error.
It's a good idea to check for an error before asking the new BMessenger to send a message. For example:
BMessenger *outlet = new BMessenger(some_signature); if ( outlet->Error() == B_NO_ERROR ) { BMessage *msg = new BMessage(CHANGE_NAME); msg->AddString("old", formerName); msg->AddString("new", currentName); outlet->SendMessage(msg); if ( outlet->Error() == B_NO_ERROR ) . . . }
A BMessenger can send messages to only one destination. Once constructed, you can cache it and reuse it repeatedly to communicate with that object. It should be freed after it's no longer needed (or if there's a long delay between messages and it's possible that the user might have quit the destination application and restarted it again, or that the application may have destroyed the target BHandler).
The BRoster object can provide signature and team information about possible destinations.
See also: the BRoster and BMessage classes, Error()
~BMessenger(void)
Frees all memory allocated by the BMessenger, if any was allocated at all.
long Error(void)
Returns an error code that describes what went wrong with the attempt to construct the BMessenger or to have it send a message, or B_NO_ERROR if nothing went wrong. Possible errors include:
B_BAD_VALUE | The constructor can't connect the BMessenger to the remote application, most likely because an application with the specified signature isn't running. |
B_MISMATCHED_VALUES | The constructor failed because the specified signature and team arguments designated two different applications. |
B_BAD_TEAM_ID | The constructor can't establish a connection to the specified team, most likely because there is no such team. |
B_BAD_HANDLER | The BHandler passed to the constructor was not associated with a BLooper. |
B_BAD_PORT_ID | SendMessage() can't deliver the message, most likely because the destination application has been killed. |
Calling this function resets the error code to B_NO_ERROR , so you must cache the value returned if you need to check the current error more than once.
BMessenger FindHandler(BMessage *message) BMessenger FindHandler(long index, const char *class = NULL) BMessenger FindHandler(const char *name, const char *class = NULL) BMessage *FindAllHandlers(const char *class = NULL)
These functions send a B_HANDLERS_REQUESTED message and wait for a B_HANDLERS_INFO reply.
The message is passed to FindHandler() should have B_HANDLERS_REQUESTED as the what data member and should ask for a BMessenger for just one BHandler. If an index or a name is passed instead of a message, FindHandler() creates the message and adds that information in an entry named "index" or "name". If the index or name is restricted to a class, it adds the class name in an entry labeled "class".
When it gets the reply, FindHandler() returns the requested BMessenger. It may register a B_ERROR, B_NAMED_NOT_FOUND, or B_BAD_INDEX error taken from the reply, or a B_BAD_PORT_ID error if there's a problem sending the message. In the case of any error, the BMessenger is not to be trusted.
FindAllHandlers() requests BMessengers for a group of BHandlers, which may be restricted to a particular class. It returns the B_HANDLERS_INFO reply, or NULL if there's an error in sending a message.
See the various HandlersRequested() functions for information on the protocols that the software kits currently expect the B_HANDLERS_REQUESTED and B_HANDLERS_INFO messages to follow.
See also: BHandler::HandlersRequested()
bool IsValid(void)
Returns TRUE if the destination BLooper object to which the BMessenger sends messages remains valid, and FALSE if not (if, for example, it has been deleted).
This function doesn't check whether the target BHandler is still valid; it reports only on the status of the destination BLooper.
long SendMessage(BMessage *message, BMessage **reply) long SendMessage(ulong command, BMessage **reply) long SendMessage(BMessage *message, BHandler *replyTarget = NULL) long SendMessage(ulong command, BHandler *replyTarget = NULL)
Sends a message. The BMessage object becomes the responsibility of the BMessenger. You shouldn't try to modify it, post it, send it again, use it as a model message, or free it; it will be freed automatically when it's no longer needed.
If a command is passed instead of a full message, this function constructs a BMessage object with command as its what data member and sends it just like any other message. This is simply a convenience for sending messages that contain no data. The following two lines of code are roughly equivalent:
myMessenger->SendMessage(NEVERMORE); myMessenger->SendMessage(new BMessage(NEVERMORE));
This function can ask for a synchronous reply to the message or designate a BHandler for an asynchronous reply:
The caller is responsible for deleting the reply message. If the destination doesn't send a reply, the system sends one with B_NO_REPLY as the what data member. Check the reply message before proceeding. If there's an error in sending the message, the variable that reply refers to is set to NULL .
The replyTarget is subject to the same restriction as a target BHandler passed to the BMessenger constructor: It must be associated with a BLooper object (or be a BLooper itself) < and it must retain that association until the reply arrives >.
If all goes well, SendMessage() returns B_NO_ERROR . If not, it returns an error code, typically B_BAD_PORT_ID . The return value is also registered with the Error() function; see that function for more information.
(It's an error for a thread to send a message to itself and expect a synchronous reply. The thread can't respond to the message and wait for a reply at the same time.)
See also: BMessage::SendReply()
inline team_id Team(void)
Returns the identifier for the team that receives the messages the BMessenger sends.
BMessenger &operator =(const BMessenger &messenger)
Assigns one BMessenger to another. After the assignment the two objects are identical and independent copies of each other, with no shared data.
void *operator new(size_t numBytes)
Prevents confusion with a private version of the new operator used internally by the Application Kit. This version of new is no different from the operator used with other classes.
The Be Book, HTML Edition, for Developer Release 8 of the Be Operating System.
Copyright © 1996 Be, Inc. All rights reserved.
Be, the Be logo, BeBox, BeOS, BeWare, and GeekPort are trademarks of Be, Inc.
Last modified September 6, 1996.