use HaikuR1::Looper qw(B_LOOPER_PORT_DEFAULT_CAPACITY); # define MyLooper subclass here my $looper = MyLooper->new($name); $looper->AddHandler($handler); $looper->Run(); $looper->PostMessage($message, $handler); # looper must be locked before quitting $looper->Unlock(); $looper->Quit();
from HaikuR1.ApplicationKit import Looper, B_LOOPER_PORT_DEFAULT_CAPACITY # define MyLooper subclass here looper = MyLooper(name) looper.AddHandler(handler) looper.Run() looper.PostMessage(message, handler) # looper must be locked before quitting looper.Unlock() looper.Quit()
Creates a Looper.
my $handler = HaikuR1::Looper->new($initial, $priority, $portCapacity);
handler = Looper(initial, priority, portCapacity)
Optional; an integer priority at which the Looper's thread will run; defaults to
B_NORMAL_PRIORITY. Ignored when
initialis a Message; the priority stored in the archive is used intead.
An integer, the number of messages the Looper's port will hold; defaults to
B_LOOPER_PORT_DEFAULT_CAPACITY(currently 200). Ignored when
initialis a Message; the capacity stored in the archive is used intead.
Note: Messages from within your own team (= process) are almost always posted directly to the Looper's MessageQueue; only messages from other teams, or replies to messages sent synchronously, or messages posted to the looper's preferred handler, are sent using the port, and unless the Looper is busy doing something else, the loop at the heart of the Looper converts raw messages from the port into Message objects and places them into the queue pretty quickly. So the default is generally sufficient and you probably don't need to worry about this parameter.
These methods maintain the Looper's common filters.
A MessageFilter may only belong to one object at a time. You cannot add a MessageFilter to an object it already belongs to. (Although you can remove it and then re-add it later.)
The Looper must be locked before changing the filter list. (Although you can
CommonFilterList without locking the Looper.)
$looper->AddCommonFilter($filter); $looper->RemoveCommonFilter($filter); $looper->SetCommonFilterList($filters); $looper->CommonFilterList();
looper.AddCommonFilter(filter) looper.RemoveCommonFilter(filter) looper.SetCommonFilterList(filters) looper.CommonFilterList()
The MessageFilter to add or remove.
A list of MessageFilters, the new list.
These functions do what you expect.
A Handler must belong to a Looper before a Looper can dispatch Messages to the Handler. The Looper must be locked to change or examine its list of Handlers.
RemoveHandler returns true if the Handler was successfully removed, false
otherwise. (This includes invalid Handler objects and Handlers that do not
belong to the Looper.)
The preferred Handler is used as a target when no Handler target has been specified. Initially, it is empty, and the Looper handles such Messages itself. You can restore it to this default state by setting the empty value as the preferred Handler.
A Handler must already belong to the Looper before it can be set as the preferred Handler. Since the Handler already belongs to the Looper, the Looper does not need to be locked in order to call the preferred Handler methods.
$looper->AddHandler($handler); $looper->RemoveHandler($handler); $looper->CountHandlers(); $looper->HandlerAt($index); $looper->IndexOf($handler); $looper->PreferredHandler(); $looper->SetPreferredHandler($handler);
looper.AddHandler(handler) looper.RemoveHandler(handler) looper.CountHandlers() looper.HandlerAt(index) looper.IndexOf(handler) looper.PreferredHandler() looper.SetPreferredHandler(handler)
The Handler to add, remove, set as preferred, or determine an index for.
An integer, the index to get a Handler for.
These methods do what you expect.
LockWithTimeout signals an error if it
fails to obtain a lock.
$looper->Lock(); $looper->Unlock(); $looper->IsLocked(); $looper->LockWithTimeout($timeout);
looper.Lock() looper.Unlock() looper.IsLocked() looper.LockWithTimeout(timeout)
An integer, the timeout in microseconds.
These methods do what you expect.
return Message objects;
MessageQueue returns a MessageQueue object.
The Looper must be locked before calling
The Be Book says that detaching a message "is useful if you want to delay the response to the message without tying up the Looper". That is, you can detach it and then repost it in order to delay the processing.
However, the Be Book also warns that "if the message sender is waiting for a synchronous reply, detaching the message and holding on to it will block the sender".
$looper->CurrentMessage(); $looper->DetachCurrentMessage(); $looper->MessageQueue(); $looper->IsMessageWaiting();
looper.CurrentMessage() looper.DetachCurrentMessage() looper.MessageQueue() looper.IsMessageWaiting()
DispatchExternalMessage differs from
PostMessage in two important ways:
first, the Message is dispatched immediately without going into the queue;
second, the DispatchMessage hook runs in the caller's
thread, not in the looper's thread.
Because it is running in the caller's thread, the calling thread must Lock the Looper before calling it. It returns a boolean indicating whether sthe Message was detached during the process.
$looper->PostMessage($message, $handler, $replyTo); $looper->PostMessage($message, $looper, $replyTo); $looper->DispatchExternalMessage($message, $handler);
looper.PostMessage(message, handler, replyTo) looper.PostMessage(message, looper, replyTo) looper.DispatchExternalMessage(message, handler)
Either a Message or an integer command, the message to post.
A Handler, the target for the message; if not specified, the Looper itself will be the target; if the empty value is passed, the Looper's preferred Handler will be the target. (An actual handler must be supplied for
PostMessage, you may not omit it or pass the empty value.)
A Handler to receive the reply; if not specified, the reply is sent to
Ends the Looper's message loop. The Looper must be locked before calling this function.
Starts the Looper's message loop. The Looper must be locked before calling this function. Returns the thread id of the loop thread or signals an error.
This method can be called as a hook under certain circumstances. For example, if the Show method is called on the Looper subclass Window, and the Window's message loop has not been started, the system will call Window.Run as a hook.
Returns the team id for the Looper.
Returns the thread id for the Looper, or signals an error (for example, if there is no thread yet because you haven't called Run).
Dispatches the given message to the given handler. Override this in derived classes to handle your own messages. Always pass any messages you don't handle to Looper's version.
Other than calling the inherited version from your own hook, you never need to call this method yourself. The system will call it as necessary.
Asks the Looper if it is ready to quit. Override this in subclasses; return false to tell the caller you're not ready to quit, true to allow quitting. Looper's version returns true.
Returns the Looper that is running in the given thread.
An integer, the thread to get a Looper for.
The following methods are mainly used for debugging.
Counts the number of locks the locking thread holds on the Looper.
Counts the number of lock requests; this includes the thread currently holding the lock, plus all threads waiting to acquire the lock.
Returns the id of the thread that currently has the Looper locked, or signals
B_ERROR if the Looper is not locked.
Returns the id of the semaphore that is used to lock the Looper.
Looper inherits the methods and hooks of Archivable.
Looper inherits the methods and hooks of Handler.
The default port capacity; currently 200.
The name of Looper's scripting suite is
gets the number of Handlers in the Looper (does not seem to be working, as of Haiku revision ...) TODO: check this out
gets a set of Messengers targeting each of the Looper's Handlers (does not seem to be working, as of Haiku revision ...) TODO: check this out
targets the Looper's
indexth Handler, either from the front or the end of the list
Looper also inherits the following suites: