読者です 読者をやめる 読者になる 読者になる

ux00ff

ビールとプログラミングと

Scala, Akka, Processing

Scalaを学ぶならAkkaも学ばねばならぬ・・・という話を誰から聞いたのかは覚えていませんが、せっかくだからAkkaもProcessing文脈でやってみようと試みたのがこちら。あまりにも誰得なのですが、とはいえ書いておかないと忘れそうなので覚書です。

環境は macOS Sierra、Processing 3系、IntelliJ IDEAを利用しています。

Akkaは Maven リポジトリから落としてきます。2.4.16をここではチョイス。

f:id:ux00ff:20170201183004p:plain

あとは実装ですが、これはまず画面からのイベントを受け取る最小限の Actor を作って見ることにします。

class BaseActor extends Actor {
  val log = Logging(context.system, this)

  def receive = {
    case MouseClickEvent(x, y) => {
      log.info("click! %d,%d".format(x, y))
    }

    case _ => {
      log.debug("missing message")
    }
  }
}

object BaseActor {
  case class MouseClickEvent(x: Int, y: Int)
}

こんな感じでいいでしょう。

アプリケーション側からは、初期化時に ActorSystem と Actor の生成までやってしまうことにします。とりあえず動作したけど、ActorからPApplet側の操作をするのはどうするのが自然なんだろう。Fluxめいた感じの構成を作るのがよいのかなー。

ひとまず作って見たのがこちら。

import BaseActor
import BaseActor.MouseClickEvent

import akka.actor.{Actor, ActorSystem, Props}
import akka.event.Logging
import processing.core.PApplet

// 画面には何も出さないので灰色の画面が出るだけである
class App extends PApplet {
  val system = ActorSystem("appSystem")
  val props = Props(classOf[BaseActor])
  val baseActor = system.actorOf(props, name = "baseActor")

  override def settings(): Unit = {
    size(500, 300)
  }

  override def setup(): Unit ={
    surface.setTitle("Click Me")
  }

  // Actor にメッセージ飛ばすだけ
  override def mouseClicked(): Unit = {
    baseActor ! MouseClickEvent(mouseX, mouseY)
  }

  // これを書かないとマウスイベントも処理されないので注意する
  override def draw(): Unit = { }
}

object Main {
  def main(args: Array[String]): Unit = {
    PApplet.main("App")
  }
}

実行してみた。

f:id:ux00ff:20170201191140p:plain

クリックするとログが出る!!!!(それだけ)

ActorSystemがスレッドプール持ってて、Actorは基本的には別スレッドで動いていて、死んだり生き返ったりしつつ ActorSystem に管理されていて、思想上は別スレッドというか「メモリ空間が共用されない前提」で使う、シリアライズ可能でイミュータブルなメッセージで通信しあう、というイメージが正しいのだとすると。うっかりビューを更新する用の Actor に PApplet のインスタンス渡してしまって更新させたくなっちゃったけど、きっと間違っているんだろうなぁ。

ひとまずここまで。