Passing a value from one actor to another in scala

Can any of you please help me in understanding the basic message passing in scala using Actor Model?

I'm trying to write a simple program with 3 actors.

  1. Actor "BossActor" creates 2 actors "Actor1" and "Actor2"

  2. "Actor1" takes 2 integer arguments -> finds their sum -> passes the sum to Actor2

  3. "Actor2" prints the sum

package actorsSum

import scala.actors.Actor
import scala.actors.Actor._

case object BossActor
case object Actor1
case object Actor2

object SumOf2Numbers extends App
{

    print ("Enter Num1 : ")
    val Num1 = readInt()
    print ("Enter Num2 : ")
    val Num2 = readInt()

    var Sum = 0

    val bossActor = new BossActor(Num1,Num2,Sum)
    bossActor.start

}

/** Boss Actor which creates and controls all subsequent actors */
class BossActor(Num1: Int, Num2: Int, Sum: Int) extends Actor {
    def act() {

        val act1 = new Actor1(Num1,Num2)
        val act2 = new Actor2(Sum)
        act1.start
        act2.start

    }
}

/** Actor to find sum of the numbers */

class Actor1 (Num1: Int, Num2: Int) extends Actor {
    def act() {

        val Grandtotal = Num1 + Num2

        /** send "Grandtotal" to Actor2 */
        // act2 ! Grandtotal

    }
}

/** Actor to print the sum */

class Actor2(Sum: Int) extends Actor {
    def act() {

        react{

            /** print the sum */

            case Actor1 => println ("Sum: " + Sum)

            case Sum => println ("Sum: " + Sum)


        }
    }
}

Upvotes: 2

Views: 2087

Answers (3)

drexin
drexin

Reputation: 24413

I would take a different approach. Actors receive messages and react to them. So what you should do is build an actor that receives requests to sum 2 numbers and send them to a receiver that is also specified in the message. That could look like this:

import scala.actors.Actor

case class Sum(x: Int, y: Int)

class SumActor extends Actor {
  def act = {
    loop {
      receive {
        case (Sum(x,y), receiver: Actor) => receiver ! x+y
      }
    }
  }
}

class Receiver extends Actor {
  def act = {
    loop {
      receive {
        case x: Int => println("Received: " + x)
      }
    }
  }
}

val sumActor = new SumActor
val receiver = new Receiver

sumActor.start
receiver.start

sumActor ! Sum(3,4) -> receiver

You should also take a look at Akka, as it will replace the scala actors in future releases of scala and is way more powerful. But to understand the basics of actors it is sufficient to start with scala actors.

Upvotes: 3

tgr
tgr

Reputation: 3608

Firstly here is the running code:

import scala.actors.Actor
import scala.actors.Actor._

object Main extends App {
    print("Enter first number: ")
    private[this] val num1 = readInt()
    println(num1)
    print("Enter second number: ")
    private[this] val num2 = readInt()
    println(num2)

    private[this] val boss = new BossActor(num1, num2)
    boss.start()
}

case object Stop

class BossActor(num1: Int, num2: Int) extends Actor {
    def act {
        val sumer = new SumActor()
        val printer = new PrintingActor()
        sumer.start()
        printer.start()
        sumer ! num1
        sumer ! num2
        receive {
            case i: Int => printer ! i
        }
        sumer ! Stop
        printer ! Stop
        exit()
    }
}

class SumActor extends Actor {
    private[this] var firstOption: Option[Int] = None

    def act() {
        loop {
            react {
                case i: Int => if (firstOption.isDefined) {
                    sender ! i + firstOption.get
                    firstOption = None
                } else {
                    firstOption = Some(i)
                }
                case Stop => exit()
            }
        }
    }

}

class PrintingActor extends Actor {

    def act() {
        loop {
            react {
                case Stop => exit()
                case e => println(e)
            }
        }
    }

}

I read the numbers like you do. Than I create a new BossActor. Next the boss sends the received Int to the SumActor. The sumer adds the two values and returns them to the boss. The boss sends the sum to the PrintingActor. The printer prints the numbers. Afterwards the boss sends atermination message to his actors and terminates himself. This might be improved by sending the boss the two Int, but in this simple example it might show how to create an Actor wtih parameter.

Upvotes: 1

senia
senia

Reputation: 38045

First of all: sender(Actor1) should know about receiver(Actor2), so you should create and start receiver before sender, and pass receiver as constructor argument to sender.

Don't use var to share actor's state.

Using case objects as messages is a good idea, but you should use case class to send some value.

import scala.actors.Actor
import scala.actors.Actor._

case class Sum(i: Int)

class Sender(a1: Int, a2: Int, receiver: Actor) extends Actor {
  def act() {
    receiver ! Sum(a1 + a2)
  }
}

class Receiver extends Actor {
  def act() {
    react {
      case Sum(i) => println("Sum: " + i)
    }
  }
}

val receiver = new Receiver().start()
val sender = new Sender(1, 2, receiver).start()

You can use some helper methods from object Actor:

import scala.actors.Actor._

val receiver = actor { react { case i: Int => println("Sum: " + i) } }
val sender = actor { receiver ! 1 + 2 }

Upvotes: 1

Related Questions