| 1 |
/* |
|---|
| 2 |
* Copyright 2008, Haiku, Inc. All Rights Reserved. |
|---|
| 3 |
* Distributed under the terms of the MIT License. |
|---|
| 4 |
* |
|---|
| 5 |
* Authors: |
|---|
| 6 |
* Niels Sascha Reedijk, niels.reedijk@gmail.com |
|---|
| 7 |
* |
|---|
| 8 |
* Corresponds to: |
|---|
| 9 |
* /trunk/headers/os/app/Looper.h rev 21863 |
|---|
| 10 |
* /trunk/src/kits/app/Looper.cpp rev 21864 |
|---|
| 11 |
*/ |
|---|
| 12 |
|
|---|
| 13 |
/*! |
|---|
| 14 |
\file Looper.h |
|---|
| 15 |
\brief Provides the BLooper class. |
|---|
| 16 |
*/ |
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
/*! |
|---|
| 20 |
\def B_LOOPER_PORT_DEFAULT_CAPACITY |
|---|
| 21 |
\brief The default size of the port of a BLooper. |
|---|
| 22 |
*/ |
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
/*! |
|---|
| 26 |
\class BLooper |
|---|
| 27 |
\ingroup app |
|---|
| 28 |
\brief Receive and process messages in a separate thread. |
|---|
| 29 |
|
|---|
| 30 |
When an object of this class is created, the message loop can be started |
|---|
| 31 |
with Run(). This spawns the thread that receives messages and processes |
|---|
| 32 |
messages. Messages are actually passed on to \link BHandler handlers \endlink |
|---|
| 33 |
that are associated with this looper. By default there is always one |
|---|
| 34 |
handler available: the looper itself. To 'quit' a looper, you should pass |
|---|
| 35 |
a \c B_QUIT_REQUESTED message using one of the message post functions. When |
|---|
| 36 |
a looper receives such a request, it will \b delete itself. As such, looper |
|---|
| 37 |
should <em>always be created on the heap</em> (with \c new), and never on |
|---|
| 38 |
the stack. |
|---|
| 39 |
|
|---|
| 40 |
Posting messages can be done using the various PostMessage() methods. |
|---|
| 41 |
Whenever a message is posted, it will be added through to the message |
|---|
| 42 |
queue. It is possible to apply filters (see AddCommonFilter()) to filter |
|---|
| 43 |
out any messages that correspond with certain criteria. The method will |
|---|
| 44 |
copy the contents of the message and this copy is processed, so make sure |
|---|
| 45 |
you delete the original messages in case you create them on the heap. |
|---|
| 46 |
The handler for the message is chosen using the following criteria: |
|---|
| 47 |
|
|---|
| 48 |
-# If PostMessage() or the BMessenger is set to a specific handler, and |
|---|
| 49 |
this handler is associated with this looper, than the message is |
|---|
| 50 |
processed by that handler. |
|---|
| 51 |
-# Else, the preferred handler is used. You can set this using |
|---|
| 52 |
SetPreferredHandler(). |
|---|
| 53 |
-# If there is no preferred handler, then the looper itself will process |
|---|
| 54 |
the message. |
|---|
| 55 |
|
|---|
| 56 |
Because a looper usually is used in multiple threads, you should make sure |
|---|
| 57 |
you Lock() and Unlock() it during most operations. Locking calls can be |
|---|
| 58 |
recursive (so multiple locks can come from a single thread), but make sure |
|---|
| 59 |
you pair every Lock() with an Unlock() call. Failing to do so will |
|---|
| 60 |
inevitably cause a deadlock. |
|---|
| 61 |
|
|---|
| 62 |
Because a looper provides a separate thread, and the inherited handler is |
|---|
| 63 |
usually a default handler, you will most often use this class by |
|---|
| 64 |
subclassing it. For example, you are likely to subclass BWindow (which is |
|---|
| 65 |
derived from BLooper) to customize your window and handle the messages |
|---|
| 66 |
sent to that window. You can override Run() in case you want to perform |
|---|
| 67 |
additional tasks before (or right after) starting the message loop. You can |
|---|
| 68 |
override QuitRequested() if you want to decline quitting in certain |
|---|
| 69 |
circumstances. You can override Quit() in case you want to perform |
|---|
| 70 |
additional procedures during closing time. You can also override |
|---|
| 71 |
DispatchMessage() if you want to do something with all incoming messages |
|---|
| 72 |
before they are dispatched to a handler. |
|---|
| 73 |
|
|---|
| 74 |
BLooper is one of the major base classes of the Haiku application |
|---|
| 75 |
programmers interface. Closely related classes are BMessage, BHandler and |
|---|
| 76 |
BMessenger. It is used in the interface kit, for example by the BWindow |
|---|
| 77 |
class, which makes sure every window runs it its own thread. |
|---|
| 78 |
|
|---|
| 79 |
BLooper is a part of the chain in the eloquent messaging structure. For a |
|---|
| 80 |
proper understanding of all its facets, have a look at the \ref app_messaging |
|---|
| 81 |
"messaging overview". |
|---|
| 82 |
*/ |
|---|
| 83 |
|
|---|
| 84 |
|
|---|
| 85 |
/*! |
|---|
| 86 |
\fn BLooper::BLooper(const char* name, int32 priority, int32 port_capacity) |
|---|
| 87 |
\brief Construct a new BLooper with a \a priority and an \a capacity. |
|---|
| 88 |
|
|---|
| 89 |
The new looper is, by default, not running yet. If you have set up |
|---|
| 90 |
everything properly, you may call Run(). |
|---|
| 91 |
|
|---|
| 92 |
\attention Remember that loopers should be created on the heap, because |
|---|
| 93 |
they will \c delete themselves in the Quit() method. |
|---|
| 94 |
|
|---|
| 95 |
\param name The name of the looper. |
|---|
| 96 |
\param priority The priority of the message thread of this looper. The |
|---|
| 97 |
default priority should be good enough for most tasks. Also, some |
|---|
| 98 |
derived versions of BLooper will use a specialized priority. So it is |
|---|
| 99 |
advised to leave this setting at the default, unless you know why you |
|---|
| 100 |
would like another setting. |
|---|
| 101 |
\param port_capacity Loopers use ports to send and receive messages (see |
|---|
| 102 |
the kernel kit). Ports have a maximum capacity; if there are so many |
|---|
| 103 |
messages queued that the port is full, all other incoming messages are |
|---|
| 104 |
dropped. There are situations where the size of the port should be |
|---|
| 105 |
different from the default. This might be when your looper receives |
|---|
| 106 |
a lot of messages, or if the message handling thread runs at a lower |
|---|
| 107 |
priority than normal, which would decrease the processing speed. |
|---|
| 108 |
Finding a suitable value for these custom scenarios would be done by |
|---|
| 109 |
testing. |
|---|
| 110 |
|
|---|
| 111 |
\see Run() |
|---|
| 112 |
*/ |
|---|
| 113 |
|
|---|
| 114 |
|
|---|
| 115 |
/*! |
|---|
| 116 |
\fn BLooper::~BLooper() |
|---|
| 117 |
\brief Destruct the looper. |
|---|
| 118 |
|
|---|
| 119 |
You will never delete a looper yourself. You should pass a |
|---|
| 120 |
\c B_QUIT_REQUESTED message, or if you are destroying the looper from |
|---|
| 121 |
inside its own message handling thread, you should call Quit(). |
|---|
| 122 |
|
|---|
| 123 |
\see Quit() |
|---|
| 124 |
*/ |
|---|
| 125 |
|
|---|
| 126 |
|
|---|
| 127 |
///// Archiving ///// |
|---|
| 128 |
|
|---|
| 129 |
|
|---|
| 130 |
/*! |
|---|
| 131 |
\name Archiving |
|---|
| 132 |
*/ |
|---|
| 133 |
|
|---|
| 134 |
|
|---|
| 135 |
//! @{ |
|---|
| 136 |
|
|---|
| 137 |
|
|---|
| 138 |
/*! |
|---|
| 139 |
\fn BLooper::BLooper(BMessage *data) |
|---|
| 140 |
\brief Construct a looper from an archived message. |
|---|
| 141 |
|
|---|
| 142 |
The \a data message has to be constructed by a BLooper::Archive() call. |
|---|
| 143 |
Note that the data that is restored, is merely the port capacity and the |
|---|
| 144 |
name of the looper/handler. Other data, such as filters, is not archived by |
|---|
| 145 |
the default archiver. |
|---|
| 146 |
|
|---|
| 147 |
\warning This constructor does no type check whatsoever. Since you can pass |
|---|
| 148 |
any BMessage, you should - if you are not sure about the exact type - |
|---|
| 149 |
use the Instantiate() method, which does check the type. |
|---|
| 150 |
|
|---|
| 151 |
\see Instantiate() |
|---|
| 152 |
\see Archive() |
|---|
| 153 |
*/ |
|---|
| 154 |
|
|---|
| 155 |
|
|---|
| 156 |
/*! |
|---|
| 157 |
\fn BArchivable *BLooper::Instantiate(BMessage *data) |
|---|
| 158 |
\brief Static method to instantiate a looper from an archived message. |
|---|
| 159 |
|
|---|
| 160 |
\return A pointer to the instantiated looper, or \c NULL if the \a data |
|---|
| 161 |
is not a valid archived BLooper object. |
|---|
| 162 |
\see BLooper(BMessage* data) |
|---|
| 163 |
*/ |
|---|
| 164 |
|
|---|
| 165 |
|
|---|
| 166 |
/*! |
|---|
| 167 |
\fn status_t BLooper::Archive(BMessage *data, bool deep) const |
|---|
| 168 |
\brief Archive a looper to a message |
|---|
| 169 |
|
|---|
| 170 |
Currently, only the name and the port capacity are archived. Any other |
|---|
| 171 |
data, such as the filters, is not stored. |
|---|
| 172 |
|
|---|
| 173 |
\param data The message to archive the object in. |
|---|
| 174 |
\param deep This parameter is ignored, as BLooper does not have children. |
|---|
| 175 |
\retval B_OK Archiving succeeded. |
|---|
| 176 |
\retval B_BAD_VALUE The \a data parameter is not a valid message. |
|---|
| 177 |
\see BLooper::Instantiate(BMessage *data) |
|---|
| 178 |
*/ |
|---|
| 179 |
|
|---|
| 180 |
|
|---|
| 181 |
//! @} |
|---|
| 182 |
|
|---|
| 183 |
|
|---|
| 184 |
/*! |
|---|
| 185 |
\name Message Mechanics |
|---|
| 186 |
*/ |
|---|
| 187 |
|
|---|
| 188 |
|
|---|
| 189 |
//! @{ |
|---|
| 190 |
|
|---|
| 191 |
|
|---|
| 192 |
/*! |
|---|
| 193 |
\fn status_t BLooper::PostMessage(uint32 command) |
|---|
| 194 |
\brief Post a message with the \a command as \c what identifier to this |
|---|
| 195 |
looper. |
|---|
| 196 |
|
|---|
| 197 |
Posting a message puts it in the message queue. The message passes through |
|---|
| 198 |
the default handler chain. |
|---|
| 199 |
|
|---|
| 200 |
\param command The \c what identifier of the message that needs to be sent. |
|---|
| 201 |
|
|---|
| 202 |
\retval B_OK The operation succeeded, and the message is sent to the port. |
|---|
| 203 |
\retval B_ERROR There was a general operation error. |
|---|
| 204 |
\retval B_BAD_VALUE This looper is not yet running and therefore cannot |
|---|
| 205 |
receive messages. |
|---|
| 206 |
|
|---|
| 207 |
\see PostMessage(BMessage *) if you want to send a message with data |
|---|
| 208 |
members. |
|---|
| 209 |
\see PostMessage(uint32, BHandler *, BHandler *) if you want to send a |
|---|
| 210 |
message to a specific handler, and request a reply. |
|---|
| 211 |
\see PostMessage(BMessage *, BHandler *, BHandler *) for the same thing, |
|---|
| 212 |
but with a complete message. |
|---|
| 213 |
*/ |
|---|
| 214 |
|
|---|
| 215 |
|
|---|
| 216 |
/*! |
|---|
| 217 |
\fn status_t BLooper::PostMessage(BMessage *message) |
|---|
| 218 |
\brief Post a \a message to this looper. |
|---|
| 219 |
|
|---|
| 220 |
Posting a message puts it in the message queue. The message passes through |
|---|
| 221 |
the default handler chain. |
|---|
| 222 |
|
|---|
| 223 |
The \a message is copied, and as such, you should make sure you will not |
|---|
| 224 |
leak it. The best way to send messages is like this: |
|---|
| 225 |
|
|---|
| 226 |
\code |
|---|
| 227 |
BMessage message; |
|---|
| 228 |
message.what = B_DO_SOMETHING; |
|---|
| 229 |
message.AddString("some_data", "This is data") |
|---|
| 230 |
|
|---|
| 231 |
aLooper->PostMessage(&message); |
|---|
| 232 |
\endcode |
|---|
| 233 |
|
|---|
| 234 |
\param message The message you would like to pass to this method. |
|---|
| 235 |
|
|---|
| 236 |
\retval B_OK The operation succeeded, and the message is sent to the port. |
|---|
| 237 |
\retval B_ERROR There was a general operation error. |
|---|
| 238 |
\retval B_BAD_VALUE This looper is not yet running and therefore cannot |
|---|
| 239 |
receive messages. |
|---|
| 240 |
|
|---|
| 241 |
\see PostMessage(uint32) if you want to send a message without data |
|---|
| 242 |
members. |
|---|
| 243 |
\see PostMessage(uint32, BHandler *, BHandler *) if you want to send a |
|---|
| 244 |
message to a specific handler, and request a reply. |
|---|
| 245 |
\see PostMessage(BMessage *, BHandler *, BHandler *) for the same thing, |
|---|
| 246 |
but with a complete message. |
|---|
| 247 |
*/ |
|---|
| 248 |
|
|---|
| 249 |
|
|---|
| 250 |
/*! |
|---|
| 251 |
\fn status_t BLooper::PostMessage(uint32 command, BHandler *handler, |
|---|
| 252 |
BHandler *replyTo) |
|---|
| 253 |
\brief Send a message with the \a command as \c what identifier to the |
|---|
| 254 |
\a handler associated with this looper, and (optionally) request a |
|---|
| 255 |
reply. |
|---|
| 256 |
|
|---|
| 257 |
The target \a handler should be associated with this looper. This method |
|---|
| 258 |
bypasses the default message queue. |
|---|
| 259 |
|
|---|
| 260 |
\param command The value you want as the message's \c what identifier. |
|---|
| 261 |
\param handler The handler you would like to pass this message to. |
|---|
| 262 |
\param replyTo If you would like to request a reply, pass the handler to |
|---|
| 263 |
which this reply should be directed to. If you pass \c NULL, you will |
|---|
| 264 |
not receive a reply. |
|---|
| 265 |
|
|---|
| 266 |
\retval B_OK The operation succeeded, and the message is sent to the port. |
|---|
| 267 |
\retval B_ERROR There was a general operation error. |
|---|
| 268 |
\retval B_BAD_VALUE This looper is not yet running and therefore cannot |
|---|
| 269 |
receive messages. |
|---|
| 270 |
\retval B_MISMATCHED_VALUES The \a handler is not associated with this |
|---|
| 271 |
looper. |
|---|
| 272 |
|
|---|
| 273 |
\see PostMessage(uint32) if you want to send a message without data |
|---|
| 274 |
members. |
|---|
| 275 |
\see PostMessage(BMessage *) if you want to send a message with data |
|---|
| 276 |
members. |
|---|
| 277 |
\see PostMessage(BMessage *, BHandler *, BHandler *) if you want to send a |
|---|
| 278 |
message to a specific handler, and request a reply. |
|---|
| 279 |
*/ |
|---|
| 280 |
|
|---|
| 281 |
|
|---|
| 282 |
/*! |
|---|
| 283 |
\fn status_t BLooper::PostMessage(BMessage *message, BHandler *handler, |
|---|
| 284 |
BHandler *replyTo) |
|---|
| 285 |
\brief Send a \a message to the \a handler associated with this looper, |
|---|
| 286 |
and (optionally) request a reply. |
|---|
| 287 |
|
|---|
| 288 |
The target \a handler should be associated with this looper. This method |
|---|
| 289 |
bypasses the default message queue. |
|---|
| 290 |
|
|---|
| 291 |
The \a message is copied, and as such, you should make sure you will not |
|---|
| 292 |
leak it. The best way to send messages is like this: |
|---|
| 293 |
|
|---|
| 294 |
\code |
|---|
| 295 |
BMessage message; |
|---|
| 296 |
message.what = B_DO_SOMETHING; |
|---|
| 297 |
message.AddString("some_data", "This is data") |
|---|
| 298 |
|
|---|
| 299 |
aLooper->PostMessage(&message, aHandler); |
|---|
| 300 |
\endcode |
|---|
| 301 |
|
|---|
| 302 |
\param message The message you want to pass. |
|---|
| 303 |
\param handler The handler you would like to pass this message to. |
|---|
| 304 |
\param replyTo If you would like to request a reply, pass the handler to |
|---|
| 305 |
which this reply should be directed to. If you pass \c NULL, you will |
|---|
| 306 |
not receive a reply. |
|---|
| 307 |
|
|---|
| 308 |
\retval B_OK The operation succeeded, and the message is sent to the port. |
|---|
| 309 |
\retval B_ERROR There was a general operation error. |
|---|
| 310 |
\retval B_BAD_VALUE This looper is not yet running and therefore cannot |
|---|
| 311 |
receive messages. |
|---|
| 312 |
\retval B_MISMATCHED_VALUES The \a handler is not associated with this |
|---|
| 313 |
looper. |
|---|
| 314 |
|
|---|
| 315 |
\see PostMessage(uint32) if you want to send a message without data |
|---|
| 316 |
members. |
|---|
| 317 |
\see PostMessage(BMessage *) if you want to send a message with data |
|---|
| 318 |
members. |
|---|
| 319 |
\see PostMessage(uint32, BHandler *, BHandler *) if you want to send a |
|---|
| 320 |
message without data to a specific handler, and request a reply. |
|---|
| 321 |
*/ |
|---|
| 322 |
|
|---|
| 323 |
|
|---|
| 324 |
//! @} |
|---|
| 325 |
|
|---|
| 326 |
|
|---|
| 327 |
/*! |
|---|
| 328 |
\name Message Processing |
|---|
| 329 |
*/ |
|---|
| 330 |
|
|---|
| 331 |
|
|---|
| 332 |
//! @{ |
|---|
| 333 |
|
|---|
| 334 |
|
|---|
| 335 |
/*! |
|---|
| 336 |
\fn void BLooper::DispatchMessage(BMessage *message, BHandler *handler) |
|---|
| 337 |
\brief Dispatch a message to a handler. Override if there are messages that |
|---|
| 338 |
you want to catch before they are sent to the handlers. |
|---|
| 339 |
|
|---|
| 340 |
This method is called by the message looping thread to dispatch a message |
|---|
| 341 |
to \a handler. If you implement the BLooper class and your looper receives |
|---|
| 342 |
messages that absolutely have to be processed by the looper instead of any |
|---|
| 343 |
of the handlers, override this method. For example, the default |
|---|
| 344 |
implementation catches B_QUIT_REQUESTED messages before they are sent to |
|---|
| 345 |
the handlers, so that the looper will quit at those messages. |
|---|
| 346 |
|
|---|
| 347 |
You are discouraged from using this method to filter out any messages you |
|---|
| 348 |
do not want to process. For this, there is a more generic method using |
|---|
| 349 |
the BMessageFilter class. If you want to skip messages with certain |
|---|
| 350 |
patterns, have a look at the AddCommonFilter() and SetCommonFilterList() |
|---|
| 351 |
methods. |
|---|
| 352 |
|
|---|
| 353 |
If you do override this method, please remember to call the |
|---|
| 354 |
DispatchMessage() method of the parent class. |
|---|
| 355 |
*/ |
|---|
| 356 |
|
|---|
| 357 |
|
|---|
| 358 |
/*! |
|---|
| 359 |
\fn void BLooper::MessageReceived(BMessage *msg) |
|---|
| 360 |
\brief Process a message received by the internal handler of this looper. |
|---|
| 361 |
|
|---|
| 362 |
Reimplemented from BHandler::MessageReceived(); |
|---|
| 363 |
*/ |
|---|
| 364 |
|
|---|
| 365 |
|
|---|
| 366 |
/*! |
|---|
| 367 |
\fn BMessage* BLooper::CurrentMessage() const |
|---|
| 368 |
\brief Retrieve the current message. |
|---|
| 369 |
|
|---|
| 370 |
\attention Only call this method from within the thread that processes the |
|---|
| 371 |
messages. It contains a pointer to the message that is currently being |
|---|
| 372 |
handled. Due to the multithreaded nature of the operating system, this |
|---|
| 373 |
method will not safely let you read the message that is being processed |
|---|
| 374 |
by this handler from outside the context of the processing. If you do |
|---|
| 375 |
want to use a message outside of the processing thread, have a look at |
|---|
| 376 |
DetachCurrentMessage() to safely retrieve a message. |
|---|
| 377 |
|
|---|
| 378 |
\return A pointer to the message that is currently being processed. Note |
|---|
| 379 |
that calling it from outside the thread that processes the message, |
|---|
| 380 |
could give you a \c NULL pointer or an invalid pointer. |
|---|
| 381 |
*/ |
|---|
| 382 |
|
|---|
| 383 |
|
|---|
| 384 |
/*! |
|---|
| 385 |
\fn BMessage* BLooper::DetachCurrentMessage() |
|---|
| 386 |
\brief Get ownership of the message currently being processed. |
|---|
| 387 |
|
|---|
| 388 |
Retrieve the current message and gain ownership of it. This means that the |
|---|
| 389 |
message will not be deleted as soon as the looper is done processing it. |
|---|
| 390 |
You can then use it for different purposes. |
|---|
| 391 |
|
|---|
| 392 |
\attention Only call this method from within the thread that processes the |
|---|
| 393 |
messages. Due to the multithreaded nature of the operating system, calling |
|---|
| 394 |
it from another thread is very likely to give you an invalid or a \c NULL |
|---|
| 395 |
pointer. |
|---|
| 396 |
*/ |
|---|
| 397 |
|
|---|
| 398 |
|
|---|
| 399 |
/*! |
|---|
| 400 |
\fn BMessageQueue* BLooper::MessageQueue() const |
|---|
| 401 |
\brief Get a pointer to the internal message queue of this looper. |
|---|
| 402 |
|
|---|
| 403 |
You can use this pointer to manipulate the message queue. Note that the |
|---|
| 404 |
message that is being processed is already detached from this queue. |
|---|
| 405 |
|
|---|
| 406 |
\return A pointer to the internal message queue. |
|---|
| 407 |
*/ |
|---|
| 408 |
|
|---|
| 409 |
|
|---|
| 410 |
/*! |
|---|
| 411 |
\fn bool BLooper::IsMessageWaiting() const |
|---|
| 412 |
\brief Check if there is a message waiting. |
|---|
| 413 |
|
|---|
| 414 |
\retval true There are still messages to be processed. |
|---|
| 415 |
\retval false There is no message waiting. |
|---|
| 416 |
*/ |
|---|
| 417 |
|
|---|
| 418 |
|
|---|
| 419 |
//! @} |
|---|
| 420 |
|
|---|
| 421 |
|
|---|
| 422 |
/*! |
|---|
| 423 |
\name Handler Management |
|---|
| 424 |
*/ |
|---|
| 425 |
|
|---|
| 426 |
|
|---|
| 427 |
//! @{ |
|---|
| 428 |
|
|---|
| 429 |
|
|---|
| 430 |
/*! |
|---|
| 431 |
\fn void BLooper::AddHandler(BHandler* handler) |
|---|
| 432 |
\brief Associate a \a handler to this looper. |
|---|
| 433 |
|
|---|
| 434 |
The \a handler will be associated to this looper. By default, the handler |
|---|
| 435 |
in this looper will be chained to the supplied \a handler. |
|---|
| 436 |
|
|---|
| 437 |
\param handler The handler to associate with this looper. If the handler is |
|---|
| 438 |
already associated to another looper, the operation will fail silently. |
|---|
| 439 |
Check beforehand if you cannot be sure that the \a handler is |
|---|
| 440 |
unassociated. |
|---|
| 441 |
|
|---|
| 442 |
\see RemoveHandler() |
|---|
| 443 |
*/ |
|---|
| 444 |
|
|---|
| 445 |
|
|---|
| 446 |
/*! |
|---|
| 447 |
\fn bool BLooper::RemoveHandler(BHandler* handler) |
|---|
| 448 |
\brief Disassociate a \a handler from this looper. |
|---|
| 449 |
|
|---|
| 450 |
If the handler is disassociated, it can be reassociated to another looper. |
|---|
| 451 |
|
|---|
| 452 |
\retval true The \a handler has been removed from this looper. |
|---|
| 453 |
\retval false The \a handler was invalid. or the handler was not |
|---|
| 454 |
associated to this looper. |
|---|
| 455 |
\see AddHandler() |
|---|
| 456 |
*/ |
|---|
| 457 |
|
|---|
| 458 |
|
|---|
| 459 |
/*! |
|---|
| 460 |
\fn int32 BLooper::CountHandlers() const |
|---|
| 461 |
\brief Get the number of handlers associated with this looper. |
|---|
| 462 |
|
|---|
| 463 |
\see HandlerAt(), IndexOf() |
|---|
| 464 |
*/ |
|---|
| 465 |
|
|---|
| 466 |
|
|---|
| 467 |
/*! |
|---|
| 468 |
\fn BHandler* BLooper::HandlerAt(int32 index) const |
|---|
| 469 |
\brief Get the handler at an \a index of the list of associated handlers. |
|---|
| 470 |
|
|---|
| 471 |
\return A pointer to the handler at that \a index, or \c NULL if the |
|---|
| 472 |
\a index is out of range. |
|---|
| 473 |
|
|---|
| 474 |
\see CountHandlers(), IndexOf() |
|---|
| 475 |
*/ |
|---|
| 476 |
|
|---|
| 477 |
|
|---|
| 478 |
/*! |
|---|
| 479 |
\fn int32 BLooper::IndexOf(BHandler* handler) const |
|---|
| 480 |
\brief Get the index of the \a handler that is in the associated handler |
|---|
| 481 |
list. |
|---|
| 482 |
|
|---|
| 483 |
\return If the \a handler is not in the list, this method will return -1. |
|---|
| 484 |
Else, you will get the index of the handler in the list. |
|---|
| 485 |
*/ |
|---|
| 486 |
|
|---|
| 487 |
|
|---|
| 488 |
/*! |
|---|
| 489 |
\fn BHandler* BLooper::PreferredHandler() const |
|---|
| 490 |
\brief Get the preferred handler. |
|---|
| 491 |
|
|---|
| 492 |
\return A pointer to the preferred handler, or \c NULL if none is set. |
|---|
| 493 |
\see SetPreferredHandler() |
|---|
| 494 |
*/ |
|---|
| 495 |
|
|---|
| 496 |
|
|---|
| 497 |
/*! |
|---|
| 498 |
\fn void BLooper::SetPreferredHandler(BHandler* handler) |
|---|
| 499 |
\brief Set a preferred handler. |
|---|
| 500 |
|
|---|
| 501 |
If messages are posted to this looper using one of the PostMessage() |
|---|
| 502 |
methods without a specific BHandler argument, the messages will be handled |
|---|
| 503 |
by the looper itself (since a looper is a subclass of BHandler, this is |
|---|
| 504 |
perfectly possible). If you want to override that behavior, you should set |
|---|
| 505 |
a preferred handler. This handler will be called if incoming messages do |
|---|
| 506 |
not ask to be directly passed on to a specific handler. |
|---|
| 507 |
|
|---|
| 508 |
\param handler The preferred handler you want undesignated messages to be |
|---|
| 509 |
handled by. If you want to unset the preferred handler, pass \c NULL. |
|---|
| 510 |
If the supplied \a handler is not associated with this looper, this |
|---|
| 511 |
call will fail silently and the current preferred handler will be unset. |
|---|
| 512 |
\see PreferredHandler() |
|---|
| 513 |
*/ |
|---|
| 514 |
|
|---|
| 515 |
|
|---|
| 516 |
//! @} |
|---|
| 517 |
|
|---|
| 518 |
|
|---|
| 519 |
/*! |
|---|
| 520 |
\name Loop Control |
|---|
| 521 |
*/ |
|---|
| 522 |
|
|---|
| 523 |
|
|---|
| 524 |
//! @{ |
|---|
| 525 |
|
|---|
| 526 |
|
|---|
| 527 |
/*! |
|---|
| 528 |
\fn thread_id BLooper::Run() |
|---|
| 529 |
\brief Start the event loop. |
|---|
| 530 |
|
|---|
| 531 |
After the looper has been constructed, it needs to be started using this |
|---|
| 532 |
method. A thread will be spawned, which will receive messages. |
|---|
| 533 |
|
|---|
| 534 |
Make sure the looper is not yet running before you call this method. |
|---|
| 535 |
|
|---|
| 536 |
\return A (positive) thread id if spawning the thread succeeded, or an |
|---|
| 537 |
error code. |
|---|
| 538 |
*/ |
|---|
| 539 |
|
|---|
| 540 |
|
|---|
| 541 |
/*! |
|---|
| 542 |
\fn void BLooper::Quit() |
|---|
| 543 |
\brief Hook method that is called after a \c B_QUIT_REQUESTED message. |
|---|
| 544 |
|
|---|
| 545 |
If you want to quit and delete the looper, you should post a |
|---|
| 546 |
\c B_QUIT_REQUESTED message. This will first call the hook method |
|---|
| 547 |
QuitRequested(), which can be overridden in child classes in case there |
|---|
| 548 |
are conditions that would prevent the looper to be quit. If you really |
|---|
| 549 |
know what you are doing, and you definitely want to quit this looper, |
|---|
| 550 |
you may call this method, but only after performing a Lock() operation. |
|---|
| 551 |
|
|---|
| 552 |
Override this method if your subclass needs to perform specific clean-up |
|---|
| 553 |
tasks. Remember to call the base class implementation when you're done. |
|---|
| 554 |
|
|---|
| 555 |
\attention You will not have to delete the looper object, if a looper quits |
|---|
| 556 |
it will delete itself. |
|---|
| 557 |
*/ |
|---|
| 558 |
|
|---|
| 559 |
|
|---|
| 560 |
/*! |
|---|
| 561 |
\fn bool BLooper::QuitRequested() |
|---|
| 562 |
\brief Hook method that is called during a \c B_QUIT_REQUESTED message. |
|---|
| 563 |
|
|---|
| 564 |
This hook function is called by the looper thread when a |
|---|
| 565 |
\c B_QUIT_REQUESTED is received. The default implementation always accepts |
|---|
| 566 |
the message, but if your subclass needs a special condition to be met |
|---|
| 567 |
before actually accepting a quit message, you can test for that condition |
|---|
| 568 |
in this hook method. A good example is a window (which is a derivative of |
|---|
| 569 |
BLooper), which contains a modified document. The condition may be that a |
|---|
| 570 |
modal dialog requesting a path of action is closed. |
|---|
| 571 |
|
|---|
| 572 |
\retval true The looper can be quit and destroyed. |
|---|
| 573 |
\retval false Do not accept the quit message and continue processing |
|---|
| 574 |
messages. |
|---|
| 575 |
*/ |
|---|
| 576 |
|
|---|
| 577 |
|
|---|
| 578 |
/*! |
|---|
| 579 |
\fn bool BLooper::Lock() |
|---|
| 580 |
\brief Lock the looper. |
|---|
| 581 |
|
|---|
| 582 |
For most operations involving the internal data of the looper, you need to |
|---|
| 583 |
hold the lock. Each looper implements a global lock, which you can use to |
|---|
| 584 |
perform operations on internal data in a thread-safe manner. |
|---|
| 585 |
|
|---|
| 586 |
Do not forget to pair each Lock() request with an Unlock() request. Lock() |
|---|
| 587 |
requests can be stacked, which means that recursively locking a looper from |
|---|
| 588 |
a thread that actually holds the lock, will not cause a deadlock. See |
|---|
| 589 |
BLocker for more information on locking internals. |
|---|
| 590 |
|
|---|
| 591 |
\retval true The locking request succeeded. |
|---|
| 592 |
\retval false The locking request could not be completed. There are a |
|---|
| 593 |
variety of reasons for this to happen, for example when the looper is |
|---|
| 594 |
destroyed. |
|---|
| 595 |
\see Unlock(), LockWithTimeout(), IsLocked() |
|---|
| 596 |
*/ |
|---|
| 597 |
|
|---|
| 598 |
|
|---|
| 599 |
/*! |
|---|
| 600 |
\fn void BLooper::Unlock() |
|---|
| 601 |
\brief Unlock a locked looper. |
|---|
| 602 |
|
|---|
| 603 |
Use this method paired with Lock() calls, to release a lock. Make sure that |
|---|
| 604 |
this method is only called on a locked looper. |
|---|
| 605 |
|
|---|
| 606 |
\see Lock(), LockWithTimeout(), IsLocked() |
|---|
| 607 |
*/ |
|---|
| 608 |
|
|---|
| 609 |
|
|---|
| 610 |
/*! |
|---|
| 611 |
\fn bool BLooper::IsLocked() const |
|---|
| 612 |
\brief Check if a looper is locked. |
|---|
| 613 |
|
|---|
| 614 |
\retval true The looper is locked. |
|---|
| 615 |
\retval false The looper is not locked, or the looper has been deleted. |
|---|
| 616 |
\see Lock(), Unlock(), LockWithTimeout() |
|---|
| 617 |
*/ |
|---|
| 618 |
|
|---|
| 619 |
|
|---|
| 620 |
/*! |
|---|
| 621 |
\fn status_t BLooper::LockWithTimeout(bigtime_t timeout) |
|---|
| 622 |
\brief Lock a looper with a \a timeout. |
|---|
| 623 |
|
|---|
| 624 |
This method locks the looper like Lock(), but if the locking request does |
|---|
| 625 |
not succeed within the provided \a timeout, the method will return. |
|---|
| 626 |
|
|---|
| 627 |
\param timeout The maximum time to wait for the lock request to succeed. |
|---|
| 628 |
|
|---|
| 629 |
\retval B_OK The lock is acquired. |
|---|
| 630 |
\retval B_BAD_VALUE The looper has been destroyed. |
|---|
| 631 |
\retval "other errors" There was an error acquiring the lock. |
|---|
| 632 |
\see Lock(), Unlock(), IsLocked() |
|---|
| 633 |
*/ |
|---|
| 634 |
|
|---|
| 635 |
|
|---|
| 636 |
/*! |
|---|
| 637 |
\fn thread_id BLooper::Thread() const |
|---|
| 638 |
\brief Return the thread id of the internal message looper thread. |
|---|
| 639 |
|
|---|
| 640 |
If the looper is not yet running, this method will return 0. |
|---|
| 641 |
|
|---|
| 642 |
\see Run() |
|---|
| 643 |
*/ |
|---|
| 644 |
|
|---|
| 645 |
|
|---|
| 646 |
/*! |
|---|
| 647 |
\fn team_id BLooper::Team() const |
|---|
| 648 |
\brief Return the team id in which this looper exists. |
|---|
| 649 |
*/ |
|---|
| 650 |
|
|---|
| 651 |
|
|---|
| 652 |
/*! |
|---|
| 653 |
\fn BLooper* BLooper::LooperForThread(thread_id thread) |
|---|
| 654 |
\brief Static method to retrieve a BLooper for a specified \a thread. |
|---|
| 655 |
*/ |
|---|
| 656 |
|
|---|
| 657 |
|
|---|
| 658 |
//! @} |
|---|
| 659 |
|
|---|
| 660 |
|
|---|
| 661 |
/*! |
|---|
| 662 |
\name Loop debugging |
|---|
| 663 |
|
|---|
| 664 |
These methods may aid you in debugging problems when they occur, but do not |
|---|
| 665 |
use these in actual production code. These methods are unrealiable because |
|---|
| 666 |
they are not thread-safe, and as such are only useful in specific debugging |
|---|
| 667 |
situations. Handle with care. |
|---|
| 668 |
*/ |
|---|
| 669 |
|
|---|
| 670 |
|
|---|
| 671 |
//! @{ |
|---|
| 672 |
|
|---|
| 673 |
|
|---|
| 674 |
/*! |
|---|
| 675 |
\fn thread_id BLooper::LockingThread() const |
|---|
| 676 |
\brief Return the thread id of the thread that currenty holds the lock. |
|---|
| 677 |
*/ |
|---|
| 678 |
|
|---|
| 679 |
|
|---|
| 680 |
/*! |
|---|
| 681 |
\fn int32 BLooper::CountLocks() const |
|---|
| 682 |
\brief Return the number of recursive locks that are currently being held |
|---|
| 683 |
on this looper |
|---|
| 684 |
*/ |
|---|
| 685 |
|
|---|
| 686 |
|
|---|
| 687 |
/*! |
|---|
| 688 |
\fn int32 BLooper::CountLockRequests() const |
|---|
| 689 |
\brief Return the number of pending locks. |
|---|
| 690 |
*/ |
|---|
| 691 |
|
|---|
| 692 |
|
|---|
| 693 |
/*! |
|---|
| 694 |
\fn sem_id BLooper::Sem() const |
|---|
| 695 |
\brief Return the id of the semaphore that is used to lock this looper. |
|---|
| 696 |
*/ |
|---|
| 697 |
|
|---|
| 698 |
|
|---|
| 699 |
//! @} |
|---|
| 700 |
|
|---|
| 701 |
|
|---|
| 702 |
/*! |
|---|
| 703 |
\name Scripting Functions |
|---|
| 704 |
*/ |
|---|
| 705 |
|
|---|
| 706 |
|
|---|
| 707 |
//! @{ |
|---|
| 708 |
|
|---|
| 709 |
|
|---|
| 710 |
/*! |
|---|
| 711 |
\fn BHandler* BLooper::ResolveSpecifier(BMessage* msg, int32 index, |
|---|
| 712 |
BMessage* specifier, int32 form, const char* property) |
|---|
| 713 |
\brief Undocumented. |
|---|
| 714 |
*/ |
|---|
| 715 |
|
|---|
| 716 |
|
|---|
| 717 |
/*! |
|---|
| 718 |
\fn status_t BLooper::GetSupportedSuites(BMessage* data) |
|---|
| 719 |
\brief Undocumented. |
|---|
| 720 |
*/ |
|---|
| 721 |
|
|---|
| 722 |
|
|---|
| 723 |
//! @} |
|---|
| 724 |
|
|---|
| 725 |
|
|---|
| 726 |
/*! |
|---|
| 727 |
\name Looper Message Filters |
|---|
| 728 |
Note that filters added with these methods will be applied to all |
|---|
| 729 |
associated handlers. Have a look at the filtering methods of the BHandler |
|---|
| 730 |
class to see how filters can be applied to the inherited handler of this |
|---|
| 731 |
looper specifically. |
|---|
| 732 |
*/ |
|---|
| 733 |
|
|---|
| 734 |
|
|---|
| 735 |
//! @{ |
|---|
| 736 |
|
|---|
| 737 |
|
|---|
| 738 |
/*! |
|---|
| 739 |
\fn void BLooper::AddCommonFilter(BMessageFilter* filter) |
|---|
| 740 |
\brief Add a common filter to the list of filters that are applied to all |
|---|
| 741 |
incoming messages. |
|---|
| 742 |
|
|---|
| 743 |
Filters can only be applied once, so they cannot be shared between loopers, |
|---|
| 744 |
a handler and a looper or between two handlers. |
|---|
| 745 |
|
|---|
| 746 |
The \a filter is not copied; rather a pointer is stored. Keep the \a filter |
|---|
| 747 |
alive as long as it is used by a looper. |
|---|
| 748 |
|
|---|
| 749 |
\see RemoveCommonFilter(), SetCommonFilterList(), CommonFilterList() |
|---|
| 750 |
*/ |
|---|
| 751 |
|
|---|
| 752 |
|
|---|
| 753 |
/*! |
|---|
| 754 |
\fn bool BLooper::RemoveCommonFilter(BMessageFilter* filter) |
|---|
| 755 |
\brief Remove a \a filter from the common message filter list. |
|---|
| 756 |
|
|---|
| 757 |
Note that this will not free the memory used by the \a filter, so you |
|---|
| 758 |
should dispose of it yourself. |
|---|
| 759 |
|
|---|
| 760 |
\see AddCommonFilter(), SetCommonFilterList(), CommonFilterList() |
|---|
| 761 |
*/ |
|---|
| 762 |
|
|---|
| 763 |
|
|---|
| 764 |
/*! |
|---|
| 765 |
\fn void BLooper::SetCommonFilterList(BList* filters) |
|---|
| 766 |
\brief Set a new list of \a filters that need to be applied to all |
|---|
| 767 |
incoming messages. |
|---|
| 768 |
|
|---|
| 769 |
You are responsible for validating that all the items in the list of |
|---|
| 770 |
\a filters are actual filters. The old list is discarded; all the filters |
|---|
| 771 |
are \b destroyed. |
|---|
| 772 |
|
|---|
| 773 |
Note that filters can only be applied to one looper or handler. If any |
|---|
| 774 |
of the filters is already associated with another one, this call will fail. |
|---|
| 775 |
|
|---|
| 776 |
\see AddCommonFilter(), RemoveCommonFilter(), CommonFilterList() |
|---|
| 777 |
*/ |
|---|
| 778 |
|
|---|
| 779 |
|
|---|
| 780 |
/*! |
|---|
| 781 |
\fn BList* BLooper::CommonFilterList() const |
|---|
| 782 |
\brief Return a list of filters applied to all incoming messages. |
|---|
| 783 |
|
|---|
| 784 |
\return A pointer to the internal filter list, or \c NULL if such a list |
|---|
| 785 |
has not yet been created. Please note that you should use the internal |
|---|
| 786 |
list management functions to manipulate the internal filter list, in |
|---|
| 787 |
order to maintain internal consistency. |
|---|
| 788 |
\see AddCommonFilter(), RemoveCommonFilter(), SetCommonFilterList() |
|---|
| 789 |
*/ |
|---|
| 790 |
|
|---|
| 791 |
//! @} |
|---|
| 792 |
|
|---|
| 793 |
|
|---|
| 794 |
/*! |
|---|
| 795 |
\fn status_t BLooper::Perform(perform_code d, void* arg) |
|---|
| 796 |
\brief Internal method. |
|---|
| 797 |
*/ |
|---|
| 798 |
|
|---|
| 799 |
|
|---|
| 800 |
/*! |
|---|
| 801 |
\fn BMessage* BLooper::MessageFromPort(bigtime_t timeout) |
|---|
| 802 |
\brief Hook function to retrieve a message from the looper's port. |
|---|
| 803 |
|
|---|
| 804 |
The default implementation is called by the internal message looping thread |
|---|
| 805 |
and retrieves the next message from the port that belongs to this looper. |
|---|
| 806 |
|
|---|
| 807 |
If you use a looper in a context where it might receive messages from other |
|---|
| 808 |
sources, you can override this method in order to insert these methods into |
|---|
| 809 |
the message processing. Note that any messages that are returned by this |
|---|
| 810 |
method will be deleted by this looper, so make sure you have ownership of |
|---|
| 811 |
the message. If you override this method, remember to call the base |
|---|
| 812 |
implementation every now and then, in order to retrieve the messages |
|---|
| 813 |
arriving at the default port. |
|---|
| 814 |
*/ |
|---|
| 815 |
|
|---|
| 816 |
|
|---|
| 817 |
|
|---|