Język programowania Scala + aktorzy Akka Marek Skórkowski
Plan prezentacji: Aktorzy Akka Scala 1. Wprowadzenie (AS) 2. Scala(MS) 3. Nawiasy, kropki... (MS) 4. DSL (MS) 5. Wielodziedziczenie(MS) 6. Package Objects (AS) 7. Collections (AS) 8. Structural Types (AS) 9. Kontynuacje (AS) 1. Wprowadzenie do aktorów (AS) 2. Akka (AS) 3. FSM (AS) 4. Play 2.0 (MS)
Martin Odersky, politechnika EPFL
Kto używa dzisiaj Scali? www.scala-lang.org
Programowanie obiektowe Programowanie funkcyjne - Class, Object i Traits - var vs val - Funkcje, Higher order function - Case Marek Skórkowski
Nawiasy, kropki i operatory Marek Skórkowski
Nawiasy, kropki i operatory Marek Skórkowski
Nawiasy, kropki i operatory Marek Skórkowski
Nawiasy, kropki i operatory Marek Skórkowski
DSL http://blog.fogus.me/2009/03/26/baysick-a-scala-dsl-implementing-basic/ Marek Skórkowski
Wielodziedziczeni e Marek Skórkowski
Package Objects W każdej paczce możemy (jednorazowo) umieścić dokładnie to samo co w klasie. package pl.osec.barcamp.scala package po class Test package object po val barcampdate = 2012-03-06 def testpackageobjectmethod println( test package object method )
Package Objects Od teraz importując import pl.osec.barcamp.scala.po._ możemy używać metody testpackageobjectmethod oraz stałej barcampdate. object HelloWorld def main( args : Array[String] ) import pl.osec.barcamp.scala.po._ println( barcampdate ) testpackageobjectmethod
Collections Ogólna struktura kolekcji w Scali:
Collections parametryzajca (generics) od samego początku
Collections traity i mixiny
Collections scala.collections.mutable._ scala.collections.immutable._ mutable (zmienne) immutable (niezmienne) Metody: par - zamienia daną kolekcję na kolekcję równoległą seq - zamienia daną kolekcję na kolekcję przetwarzaną sekwencyjnie
Structural Types Ciekawostka i przyjemnostka. Tak zdefiniowana metoda: def prowadz( samochod : def start() : Unit, def stop() : Unit ) samochod.start //... samochod.stop pozwala przekazać jako argument każdy typ, który będzie miał metodę start oraz metodę stop. Obydwie metody nie biorą żadnych argumentów oraz nie zwracają nic (Unit w Scali jest jak void w Javie). Sekcja samochod : def start() : Unit, def stop() : Unit definiuje stałą samochod jako dowolny typ posiadający tak zdefiniowane metody. Nie wymaga to od nas dziedziczenia nakazanej klasy bądź implementowania wskazanego interfejsu.
Kontynuacje Kontynuacje pozwalają przerwać wykonywanie naszego kodu w oczekiwaniu na pojawienie się zasobu zewnętrznego. Kiedy się pojawi możemy go kontynuować kod "wstrzykując" owy zasób. reset // jakis nasz kod wywolany przed kontynuacja shift kontynuacja => Przykład użycia: //... connection.open // jakis nasz kod wywolany przed kontynuacja kontynuacja() // wywolanie kontynuacji // jest to operacja blokująca, jednak w tym momencie następuje nasze "zamrożenie", inny wątek zacznie kontynuować program w momencie otworzenia połączenia (lub jakiegoś błędu) // jakis nasz kod wywolany po kontynuacji val data = connection.read // tutaj znajduje sie kontynuacja connection.write( data ) connection close
Aktorzy oddzielają nas od wątków aktor może mieć na stałe przypisany wątek bądź korzystać ze wspólnej puli wątków aktorzy komunikują się przesyłając pomiędzy sobą wiadomości wiadomością może być dowolny obiekt Java (w przypadku zdalnych aktorów obiekt musi być serializowalny) każdy aktor ma swój mailbox z którego ściąga oczekujące wiadomości i przetwarza je szeregowo Dzięki aktorom: możemy pisać programy wydajnie wykorzystujące dostępną ilość procesorów i rdzeni oddzielamy się od fizycznego zasobu jakim jest wątek dzięki czemu możemy przesłać poprzez sieć referencje do aktora lub możemy przesłać na inną maszynę całego aktora
www.akka.io
Aktorzy Akka (2.0) profesjonalny framework z aktorami API dla Scali jak i dla Javy wiele różnych podsystemów aktorów w tej samej JVM... a nawet w tym samym ClassLoader, każdy może posiadać odmienną konfigurację przeźroczystość lokalizacyjna jeśli posiadamy referencję do aktora to możemy wysyłać i odbierać od niego wiadomości bez wiedzy czy jest on lokalnym aktorem, zdalnym oraz czy podczas rozmowy z nim nie zmienił swojej lokalizacji hierarchia każdy aktor ma swojego rodzica oraz swoje dzieci (aktorzy powołani przez niego do życia), każdy nasz top-level aktor ma rodzica w postaci głównego aktora Akka TypedActor system podobny do proxy w Javie, podając trait (interfejs) oraz instancję klasy (domiksowującą ten trait) uzyskujemy obiekt na rzecz którego najnormalniej w świecie wywołujemy metody - są one jednak zamieniane na wiadomości i przesyłane do aktora, gdzie wywołują się szeregowo STM i Transactor
Aktorzy Akka (2.0) FSM Finite State Machine pozwalają nam zamienić aktora (który w dowolnym momencie może otrzymać dowolną wiadomość) na maszynę stanów object Stream sealed trait States case object NotConnected extends States case object Connecting extends States case object Connected extends States sealed trait Messages case class Connect( ip : String, port : Int ) extends Messages case class Connected( socket : Socket ) extends Messages case class Send( bytearray : Array[ Byte ] ) extends Messages case object Disconnect extends Messages
FSM cd.... class SocketStreamActor extends Actor with FSM[ Stream.States, Unit ] import FSM._ // --------------------------------------when( Stream.NotConnected ) case Ev( Stream.Connect( ip, port ) ) => // wyrzucamy rzadanie polaczenia do jakiegos zewnetrznego aktora, ktory odesle nam odpowiedz goto( Stream.Connecting ) // ---------------------------------------
FSM cd.... // --------------------------------------when( Stream.Connecting ) case EV( Strean.Connected( socket ) ) => // zapamietujemy sobie otrzymany socket goto( Stream.Connected ) case Ev( Stream.Disconnect ) => log.debug( "received disconnecting request" ) stop( Normal ) // ---------------------------------------
FSM cd.... // --------------------------------------when( Stream.Connected ) case Ev( Stream.Send( bytearray ) ) => // wysylanie danych z bytearray stay case Ev( Stream.Disconnect ) => log.debug( "received disconnecting request" ) stop( Normal ) // ---------------------------------------
FSM cd.... // --------------------------------------whenunhandled case Ev( message ) => log.debug( "received unhandled message " + message ) stay // --------------------------------------ontransition case fromstate -> tostate => log.debug( "changing state from " + fromstate + " to " + tostate ) // ---------------------------------------
FSM cd.... // --------------------------------------ontermination case StopEvent( stoptype, state, data ) => log.debug( "stopping, stoptype " + stoptype + ", state " + state + ", data " + data ) // kod na zakonczenie // --------------------------------------startwith( Stream.NotConnected, null ) initialize
FSM cd.... Gotowe! val actorsystem = ActorSystem( "ArduinoTesterActorSystem" ) // tworzymy system aktorow (mozemy miec ich wiele w JVM, kazdy z nich // moze miec inna konfiguracje val streamactor = actorsystem.actorof( Props[SocketStreamActor], name = "SocketStreamActor" ) streamactor! new Stream.Connect( "192.168.10.90", 15123 ) // aktor przechodzi ze stanu NotConnected do Connecting // jesli polaczenie sie uda to przechodzi do stanu Connected wpp. // przechodzi do zakonczenia swojej pracy streamactor! new Stream.Send( "ala ma kota".getbytes ) // polaczonemu aktorowi nadajemy wiadomosc nakazujaca nadanie bajtow streamactor! Stream.Disconnect
Play 2.0 Marek Skórkowski
Dziękujemy :) stanek.artur@gmail.com marun.skor@gmail.com www.scala.net.pl