-
Notifications
You must be signed in to change notification settings - Fork 1
Bind
In the bind package, actors bind application request classes to MessageLogic objects. This speeds up some corner cases, like returning a constant or concurrent data structure, or forwarding a request to another actor. This also means an actor can invoke a method on the target actor directly when either the target actor has no exchange messenger or both the source and target actors share the same exchange messenger--which turns out to be a very common occurrence.
The downside to binding is the cost of doing a table lookup, but this is typically mitigated entirely by the increased efficiency in most cases. In the case where neither actor has an exchange messenger, the EchoTimingTest passes a message in 83 nanoseconds and the BurstTimingTest passes a message in 84 nanoseconds.
Exception handling is also supported by the bind package, with the default exception handler simply passing the exception to the actor which sourced the current request. A TransparentException wrapps an exception which occurs while processing a [synchronous] response, so that the original exception can be passed to the source actor's exception handler rather than to the target actor's exception handler.
Finally, requests are marked as active until a response is returned or an exception is raised. By this means we can assure that for each request there is no more than one response or raised exception.
##BindRequest
/**
* BindActor and Mailbox support only BindRequests and its subclasses.
*/
class BindRequest(dst: BindActor,
rf: Any => Unit,
data: AnyRef,
bound: QueuedLogic,
src: ExchangeMessengerSource)
extends ExchangeRequest(src, rf) {
/**
* Set to false when a response is returned or an exception is raised,
* active is used to ensure that there is only one response or exception
* for each request.
*/
var active = true
/**
* Default logic when no other exception handler is used.
* (Each application request class can have its own logic for
* handling exceptions.)
*/
var exceptionFunction: (Exception, ExchangeMessenger) => Unit = {
(ex, exchange) => reply(exchange, ex)
}
/**
* The actor which is to process the request.
*/
def target = dst
/**
* The application-specific request.
*/
def req = data
/**
* The message logic object used to process the request.
*/
def binding = bound
/**
* If the request is still active, mark the request as inactive and send
* the response.
*/
override def reply(exchangeMessenger: ExchangeMessenger, content: Any) {
if (!active) {
return
}
active = false
super.reply(exchangeMessenger, content)
}
}
##ActiveActor
##BindActor
##Bindings
##BoundFunction
##ConcurrentData
##Forward
##Mailbox
##MailboxFactory
##MessageLogic
##QueuedLogic
##TransparentException
##Future
##Interop