h3. Dynamic Dispatch Actor

The _DynamicDispatchActor_ class is an actor allowing for an alternative structure of the message handling code. In general _DynamicDispatchActor_ repeatedly scans for messages and dispatches arrived messages to one
of the _onMessage(message)_ methods defined on the actor. The _DynamicDispatchActor_ leverages the Groovy dynamic method dispatch mechanism under the covers.
Since, unlike _DefaultActor_ descendants, a _DynamicDispatchActor_ not _ReactiveActor_ (discussed below) do not need to implicitly remember actor's state between subsequent
message receptions, they provide much better performance characteristics, generally comparable to other actor frameworks, like e.g. Scala Actors.

{code}
import groovyx.gpars.actor.Actors
import groovyx.gpars.actor.DynamicDispatchActor

final class MyActor extends DynamicDispatchActor {

    void onMessage(String message) {
        println 'Received string'
    }

    void onMessage(Integer message) {
        println 'Received integer'
        reply 'Thanks!'
    }

    void onMessage(Object message) {
        println 'Received object'
        sender.send 'Thanks!'
    }

    void onMessage(List message) {
        println 'Received list'
        stop()
    }
}

final def myActor = new MyActor().start()

Actors.actor {
    myActor 1
    myActor ''
    myActor 1.0
    myActor(new ArrayList())
    myActor.join()
}.join()
{code}

In some scenarios, typically when no implicit conversation-history-dependent state needs to be preserved for the actor, the dynamic dispatch code structure may be more intuitive than the traditional one using nested _loop_ and _react_ statements.

The _DynamicDispatchActor_ class also provides a handy facility to add message handlers dynamically at actor construction time or any time later
using the _when_ handlers, optionally wrapped inside a _become_ method:

{code}
final Actor myActor = new DynamicDispatchActor().become {
    when {String msg -> println 'A String'; reply 'Thanks'}
    when {Double msg -> println 'A Double'; reply 'Thanks'}
    when {msg -> println 'A something ...'; reply 'What was that?';stop()}
}
myActor.start()
Actors.actor {
    myActor 'Hello'
    myActor 1.0d
    myActor 10 as BigDecimal
    myActor.join()
}.join()
{code}

Obviously the two approaches can be combined:
{code}
final class MyDDA extends DynamicDispatchActor {

    void onMessage(String message) {
        println 'Received string'
    }

    void onMessage(Integer message) {
        println 'Received integer'
    }

    void onMessage(Object message) {
        println 'Received object'
    }

    void onMessage(List message) {
        println 'Received list'
        stop()
    }
}

final def myActor = new MyDDA().become {
    when {BigDecimal num -> println 'Received BigDecimal'}
    when {Float num -> println 'Got a float'}
}.start()
Actors.actor {
    myActor 'Hello'
    myActor 1.0f
    myActor 10 as BigDecimal
    myActor.send([])
    myActor.join()
}.join()
{code}

The dynamic message handlers registered via _when_ take precedence over the static _onMessage_ handlers.

{note}
_DynamicDispatchActor_ can be set to behave in a fair on non-fair (default) manner. Depending on the strategy chosen, the actor
either makes the thread available to other actors sharing the same parallel group (fair), or keeps the thread fot itself
until the message queue gets empty (non-fair). Generally, non-fair actors perform 2 - 3 times better than fair ones.

Use either the _fairMessageHandler()_ factory method or the actor's makeFair() method.

{note}

{code}
    def fairActor = Actors.fairMessageHandler {...}
{code}

h3. Static Dispatch Actor

While _DynamicDispatchActor_ dispatches messages based on their run-time type and so pays extra performance penalty for each message,
_StaticDispatchActor_ avoids run-time message checks and dispatches the message solely based on the compile-time information.

{code}
final class MyActor extends StaticDispatchActor<String> {
    void onMessage(String message) {
        println 'Received string ' + message

        switch (message) {
            case 'hello':
                reply 'Hi!'
                break
            case 'stop':
                stop()
        }
    }
}
{code}

Instances of _StaticDispatchActor_ have to override the _onMessage_ method appropriate for the actor's declared type parameter.
The _onMessage(T message)_ method is then invoked with every received message.

A shorter route towards both fair and non-fair static dispatch actors is available through the helper factory methods:

{code}
final actor = staticMessageHandler {String message ->
    println 'Received string ' + message

    switch (message) {
        case 'hello':
            reply 'Hi!'
            break
        case 'stop':
            stop()
    }
}

println 'Reply: ' + actor.sendAndWait('hello')
actor 'bye'
actor 'stop'
actor.join()
{code}

Although when compared to _DynamicDispatchActor_ the  _StaticDispatchActor_ class is limited to a single handler method,
the simplified creation without any _when_ handlers plus the considerable performance benefits should make _StaticDispatchActor_
your default choice for straightforward message handlers, when dispatching based on message run-time type is not necessary.
For example, _StaticDispatchActors_ make dataflow operators four times faster compared to when using _DynamicDispatchActor_ .

h3. Reactive Actor

The _ReactiveActor_ class, constructed typically by calling _Actors.reactor()_ or _DefaultPGroup.reactor()_, allow for more event-driven like approach. When a reactive actor receives a message, the supplied block of code, which makes up the reactive actor's body, is run with the message as a parameter. The result returned from the code is sent in reply.

{code}
final def group = new DefaultPGroup()

final def doubler = group.reactor {
    2 * it
}

group.actor {
    println 'Double of 10 = ' + doubler.sendAndWait(10)
}

group.actor {
    println 'Double of 20 = ' + doubler.sendAndWait(20)
}

group.actor {
    println 'Double of 30 = ' + doubler.sendAndWait(30)
}

for(i in (1..10)) {
    println "Double of $i = ${doubler.sendAndWait(i)}"
}

doubler.stop()
doubler.join()
{code}

Here's an example of an actor, which submits a batch of numbers to a _ReactiveActor_ for processing and then prints the results gradually as they arrive.

{code}
import groovyx.gpars.actor.Actor
import groovyx.gpars.actor.Actors

final def doubler = Actors.reactor {
    2 * it
}

Actor actor = Actors.actor {
    (1..10).each {doubler << it}
    int i = 0
    loop {
        i += 1
        if (i > 10) stop()
        else {
            react {message ->
                println "Double of $i = $message"
            }
        }
    }
}

actor.join()
doubler.stop()
doubler.join()
{code}

Essentially reactive actors provide a convenience shortcut for an actor that would wait for messages in a loop, process them and send back the result. This is schematically how the reactive actor looks inside:

{code}
public class ReactiveActor extends DefaultActor {
    Closure body

    void act() {
        loop {
            react {message ->
                reply body(message)
            }
        }
    }
}
{code}

{note}
_ReactiveActor_ can be set to behave in a fair on non-fair (default) manner. Depending on the strategy chosen, the actor
either makes the thread available to other actors sharing the same parallel group (fair), or keeps the thread fot itself
until the message queue gets empty (non-fair). Generally, non-fair actors perform 2 - 3 times better than fair ones.

Use either the _fairReactor()_ factory method or the actor's makeFair() method.

{note}

{code}
    def fairActor = Actors.fairReactor {...}
{code}

