$BJB9T%7%9%F%`(B $B%7%9%F%`>pJs7O(B/$B>pJs9)3X0h(B, $B%7%9%F%`>pJs9)3X8&5f72(B/$B>pJsM}9)3X0L%W%m%0%i%`(B $B%7%9%F%`>pJs9)3X8&5f2J(B/$B%3%s%T%e!<%?%5%$%(%s%9@l96(B $B?7>k(B $BLw(B <yas@cs.tsukuba.ac.jp>
$B$3$N%Z!<%8$O!"
http://www.cs.tsukuba.ac.jp/~yas/cs/csys-2021/2021-06-11
$B$"$k$$$O!"
http://www.cs.tsukuba.ac.jp/~yas/cs/
http://www.cs.tsukuba.ac.jp/~yas/
$B;29MJ88%(B References
$B8@8l$H$7$F$O!"2?
$B8=:_$G$O!"%"%/%?$r!V(B($BJB9T(B)$B%*%V%8%'%/%H!W$HFI$_BX$($k$HJ,$+$j$d$9$$!#(B
$B?^(B? $B%"%/%?$N4pK\35G0(B/Basic concepts of the Actor model
$B%"%/%?$O!"%a%C%;!<%8$r
$B%"%/%?$,%a%C%;!<%8$r
$BMWAG(B
$B%"%/%?$O!"%a%C%;!<%8$rAw$B"!7QB3(B/Continuations
$B7QB3(B(continuation$B!"7QB3E@$H$b$$$&(B)$B$rMQ$$$k!#(B
$B5f6K$N(B goto $BJ8!#(BC $B8@8l$N4X?t$G(B
goto f(1, 2, 3);
$B$N$h$&$J$b$N!#(B
$BDL>o$N3,>h(B(in Scheme)
(define (fact n) (if (= n 0) 1 (* n (fact (- n 1)))))$B7QB3$r
(define (fact-c n c) (if (= n 0) (c 1) (let ((c2 (lambda (x) (c (* n x))))) (fact-c (- n 1) c2))))
$B
6
> (fact 4)
24
> (fact-c 3 print)
6> (fact-c 4 print)
24>
factorial$B-q&K(Bm. match m <n c> if n = 1 then (send c <1>) else if n > 1 then (send factorial <(n-1) ($B&K(Bk.(send c <n * k>))>)3$B$N3,>h$r7W;;$7$F!"7QB3(Bprint_answer$B$KAw$j$?$$;~$K$O!"(B $B (send factorial <3 print_answer>)
(define (Factorial( )) (Is-Communication (a doit (with customer =m) (with number =n)) do (become Factorial) (if (NOT (= n 0)) (then (send m 1)) (else (let (x = (new FactCust (with customer m) (with number n))) (send Factorial (a do (with customer x) (with number (- n 1))))))))) (define (FactCust (with customer =m) (with number =n)) (Is-Communicaton (a number k) do (send m (* n k))))
$B?6$kIq$$5-=R(B (define ($BL>A0(B (with id $B%Q%?%s(B)) $BDL?.%O%s%I%i$NJB$S(B) $BDL?.%O%s%I%i(B (Is-Communication $B%Q%?%s(B do $B%3%^%s%I(B) let$B%3%^%s%I(B (let ($BJQ?tL>(B = $B<0(B) do $B%3%^%s%I(B) $B>r7o%3%^%s%I(B (if $B<0(B (then do $B%3%^%s%I$NJB$S(B) (else do $B%3%^%s%I$NJB$S(B)) $B%a%C%;!<%8Aw?.%3%^%s%I(B (send $B%a!<%k%\%C%/%9(B $BCM(B) becom$B%3%^%s%I(B (become $B<0(B) $B?7$7$$%"%/%?$N@8@.(B (new $B<0(B)
(define (Account (with Balance =b)) (Is-Request (a Balance) do (become (Account (with Balance b))) (reply b)) (Is-Request (a Deposit (with Amount =a)) do (become (Account (with Balance (+ b a)))) (reply (a Deposit-Receipt (with Amount a)))) (Is-Request (a Withdrawal (with Amount =a)) do (if (> a b) (then do (become (Account (with Balnce b))) (complain (an Overdraft))) (else do (become (Account (with Balnce(- b a)))) (reply (a Withdrawal-Receipt (with Amount a)))))))
import akka.actor.typed.scaladsl.Behaviors import akka.actor.typed.{ActorRef, Behavior} object Counter { sealed trait Command case object Increment extends Command final case class GetValue(replyTo: ActorRef[Value]) extends Command final case class Value(n: Int) def apply(): Behavior[Command] = counter(0) private def counter(n: Int): Behavior[Command] = Behaviors.receive { (context, message) => //$B"(#1(B message match { case Increment => val newValue = n + 1 context.log.debug("Incremented counter to [{}]", newValue) counter(newValue) //$B"((B2 case GetValue(replyTo) => replyTo ! Value(n) Behaviors.same } } }
// This function launches a new counter actor fun CoroutineScope.counterActor() = actor<CounterMsg> { var counter = 0 // actor state for (msg in channel) { // iterate over incoming messages when (msg) { is IncCounter -> counter++ is GetCounter -> msg.response.complete(counter) } } }
fun main() = runBlocking { val counter = counterActor() // create the actor withContext(Dispatchers.Default) { massiveRun { counter.send(IncCounter) } } // send a message to get a counter value from an actor val response = CompletableDeferred<Int>() counter.send(GetCounter(response)) println("Counter = ${response.await()}") counter.close() // shutdown the actor }
a = actor {...}
$B$G!"%"%/%?@8@.!#L58B%k!<%W4^$`!#(B
defmodule Counter do def start(initial_count) do spawn fn -> listen(initial_count) end end def listen(count) do receive do :inc -> listen(count + 1) {sender, :val} -> send sender, count listen(count) end end end iex> counter_pid = Counter.start(10) #PID<...> iex> send counter_pid, :inc :inc iex> send counter_pid, :inc :inc iex> send counter_pid, :inc :inc iex> send counter_pid, {self, :val} {#PID<...>, :val} iex> receive do ...(13)> value -> value ...(13)> end 13
$B%+%&%s%?$NNc!#(B
1: #!/opt/local/bin/ruby3.0 2: 3: Warning[:experimental] = false 4: 5: class CounterActor 6: def initialize(val) 7: @r = Ractor.new(val) {|val| 8: loop { 9: msg = Ractor.receive() 10: case msg 11: in [:inc] 12: val += 1 13: in [:getvalue, c] 14: c.send(val) 15: end 16: } 17: } 18: end 19: def send( msg ) 20: @r.send( msg ) 21: end 22: end 23: 24: c = CounterActor.new(10) 25: 26: c.send([:inc]) 27: c.send([:inc]) 28: c.send([:getvalue, Ractor.current()]) 29: v = Ractor.receive() 30: printf("Counter value == %d\n",v)$B
$B#13,=R8lO@M}$NO@M}<0$O!"
P 1 $B"K(B P 2 $B"K(B ... $B"K(B P n $B"+(B Q 1 $B"J(B Q 2 $B"J(B ... $B"J(B Q n.
$B!V"+!W$N:8$,$?$+$@$+(B1$B8D$N$b$N$,%[!<%s@a(B(Horn clause)$B!#(B(OR$B$,J#?t=q$-$?$/(B
$B$J$C$?$i!"J#?t9T$K$o$?$C$F=q$/(B)$B!#%[!<%s@a$K$O(B3$B
fatherof(isaac,abraham). -- isaac $B$NIc$O(B abraham $B$G$"$k(B fatherof(ishmail,abraham). fatherof(shuah,abraham). fatherof(jacob,isaac). fatherof(esau,isaac). fatherof(reuben,jacob). fatherof(dinah,jacob). fatherof(dan,jacob). fatherof(asher,jacob). fatherof(joseph,jacob). motherof(isaac,sarah). -- isaac $B$NJl$O(B sarah $B$G$"$k!#(B motherof(ishmail,hagar). motherof(shuah,ketura). motherof(jacob,rebeccah). motherof(easu,rebeccah). motherof(reuben,leah). motherof(dinah,leah). motherof(dan,bilhah). motherof(asher,zilpah). motherof(joseph,rachel).
"_"
$B$O!"L5L>JQ?t!#CM$O;D$i$J$$!#(B
"motherof(isaac,_)?"
$B$N"fatherof(_,_)"
$B$N"fatherof(joseph,X)"
$B$N"X"
$B$O!"(B"jacob"
$B$KB+G{(B(bind)$B$5$l$F$$$k!#(B
"motherof(C,leah)?"
$B$N"C=dinah"
$B$H$$$&B+G{$,5/$-$k$3$H$,$"$k!#(B
parentof(C,P) :- motherof(C, P). -- P $B$,(B C $B$NJl$J$i!"(B P $B$O(B C $B$N?F$G$"$k!#(B parentof(C,P) :- fatherof(C, P). -- P $B$,(B C $B$NIc$J$i!"(B P $B$O(B C $B$N?F$G$"$k!#(B grandparentof(C,GP) :- parentof(C,P), parentof(P,GP). -- C $B$N?F$,(B P $B$G!"$+$D!"(BP $B$N?F$,(B GP $B$J$i!"(BGP $B$O(B C $B$NADIcJl$G$"$k!#(B ancestor(C,A) :- parentof(C,A). ancestor(C,A) :- parentof(C,P), ancestor(P,A). -- C $B$N?F$,(B P $B$G!"$+$D!"(BP $B$NAD@h$,(B A $B$J$i$P!"(BA $B$O(B C $B$NAD@h$G$"$k!#(B
append([],Y,Y). append([A|B],Y,[A|B1]) :- append(B,Y,B1).
$B?^(B? Prolog $B$N(B append
quicksort(List,Sorted) :- qsort(List, Sorted, []). qsort([],H,H). qsort([A|B],H,T) :- partition(B,A,S,L), qsort(S,H,[A|T1]), qsort(L,T1,T). partition([],X,[],[]). partition([A|B],X,[A|S],L) :- A<X, partition(B,X,S,L). partition([A|B],X,S,[A|L]) :- A>=X, partition(B,X,S,L).
$B?^(B? Prolog $B$K$h$k%/%$%C%/%=!<%H(B
quicksort $B$K$"$kJBNs@-!#(BParallelism in quicksort.H :- G 1, G 2,...,G n | B 1, B 2, ..., B m.
$B!V(B|$B!W$O!"%3%_%C%H1i;;;R!#(B G 1, G 2,...,G n $B$O%,!<%IIt!#(B B 1, B 2, ..., B m $B$O!"%\%G%#It!#(Bappend([A|X1],Y,Z) :- true | Z = [A|Z1], append(X1,Y,Z1). append([],Y,Z) :- true | Z=Y.Prolog $B$J$i$3$&$J$k(B
append([A|X1],Y,[A|Z1]) :- append(X1,Y,Z1). append([],Y,Y).
quicksort(Xs,Ys) :- true | qsort(Xs, Ys-[]). qsort([X|Xs],Ys0-Ys3) :- true | partition(Xs,X,S,L), qsort(S,Ys0-Ys1), Ys1=[X|Ys2], qsort(L,Ys2-Ys3). qsort([],Ys0-Ys1) :- true | Ys0 = Ys1. partition([X|Xs],A,S,L0) :- A<X | L0=[X|L1], partition(Xs,A,S,L1). partition([X|Xs],A,S0,L) :- A>=X | S0=[X|S1], partition(Xs,A,S1,L). partition([],A,S,L) := true | S=[], L=[].
1999$BG/$K!"%5%s!&%^%$%/%m%7%9%F%`%:
Jini $B$NL\I8$O!"%M%C%H%o!<%/$G(B Plug & Play $B$r
$BL\I8(B
JavaSpaces $B$O!"FbItE*$K(B Jini $B$N%k%C%/%"%C%W!&%5!<%S%9$N
Jini $B$N%/%i%9%i%$%V%i%j$O!"(B
JavaSpaces $B$N2s(B
$B$G>R2p$7$?(B
Apache River
$B$,MxMQ$G$-$k!#(B
Microsoft $B$N!"(BJini $B$KBP93$7$?5;=Q!#(B
$B"!(BUPnP (Universal Plugand Play)
$B"!%k%C%/%"%C%W!&%5!<%S%9(B/Loockup service in Jini
Jini$BCf?4E*$J5;=Q$,!"%k%C%/%"%C%W!&%5!<%S%9!#(B
$B%5!<%S%9$NEPO?$H8!:w(B
$B%k%C%/%"%C%W!&%5!<%S%9<+?H$b!":G=i$+$iCN$i$l$F$$$kI,MW$O$J$$!#(B $B%M%C%H%o!<%/>e$G<+F0E*$KC5$5$l$k!#(B Discovery $B$H(B Join$B!#(B
Java $B$N%*%V%8%'%/%H$,(B Lease$B!#(B
$B%j!<%94|4V$O!"1dD9$9$k$3$H$,$G$-$k!#(B $B1dD9$5$l$J$+$C$?(B lease $B$O!"%k%C%/%"%C%W!&%5!<%S%9$+$i:o=|$5$l$k!#(B $BEPO?$5$l$F$$$k%5!<%S%9$rL@<(E*$K:o=|$9$k;EAH$_$O!"B8:_$7$J$$!#(B
$B%5!<%S%9$,:o=|$5$l$?;~$K$O!"J,;67?%$%Y%s%HG[Aw%5!<%S%9$K$h$j4X78$7$F$$(B $B$k=j$KCN$i$5$l$k!#(B
$B%H%i%s%6%/%7%g%s$N%$%s%?%U%'!<%9$ODj$a$i$l$F$$$k$,!"6qBNE*$J
$B"!(BJini$B$r;H$&$N$KI,MW$H$5$l$F$$$k$b$N(B/Requirements to run Jini
IP$B%"%I%l%9$N3d$jEv$F$O!"(BJini$B$N0lIt$G$O$J$$!#(B
$B%5!<%S%9$NDs6!
ServiceIDLister $B%$%s%?%U%'!<%9$r(B implements $B$9$k!#(B
package com.sun.jini.lookup;
public interface ServiceIDListener extends java.util.EventListener {
void serviceIDNotify(net.jini.core.lookup.ServiceID serviceID);
}
$B%k%C%/%"%C%W!&%5!<%S%9$+$i%3!<%k%P%C%/$5$l$k!#(B
Discovery $B$N
$B?^(B1 $B%^%k%A%-%c%9%H$K$h$k(B Discovery/Discovery by multicast
$B?^(B2 Join
$B%0%k!<%W$O!"L>A0(B($BJ8;zNs(B)$B$G6hJL$5$l$k!#(B
Jini $B%Q%C%1!<%8$O!"(BJoinManager $B$H$$$&;2>H%/%i%9$r4^$`!#(B
public JoinManager(Object obj, Entry[] attrSets, ServiceIDListener callback, LeaseRenewalManager leaseMgr) throws IOException public JoinManager(Object obj, Entry[] attrSets, String[] groups, LookupLocator[] locators, ServiceIDListener callback, LeaseRenewalManager leaseMgr ) throws IOException
import java.rmi.*; public interface RemoteBall extends Remote { public void hit() throws java.rmi.RemoteException; }
import java.rmi.*; import java.rmi.server.*; import net.jini.core.lookup.*; import com.sun.jini.lookup.*; public class Ball extends UnicastRemoteObject implements RemoteBall, ServiceIDListener { public Ball() throws RemoteException { super(); } public void serviceIDNotify(ServiceID id) { System.out.println("ServiceId is "+id); } public void hit() { System.out.println("Ball has been hit"); } }
import java.rmi.*; import net.jini.core.entry.*; import net.jini.lookup.entry.*; import com.sun.jini.lookup.*; import com.sun.jini.lease.*; public class BallStarter { public static void main(String[] args) { try { System.setSecurityManager(new RMISecurityManager()); RemoteBall ball = (RemoteBall) new Ball(); LeaseRenewalManager renewal = new LeaseRenewalManager(); Entry[] attributes = new Entry [] { new Name("Jini enabled ball")}; JoinManager join = new JoinManager( ball, attributes, (Ball) ball, renewal ); System.out.println("Ball started and registered at Lookup-Server"); } catch (Exception e) { e.printStackTrace(); } } }
$B?^(B3 Lookup
$B%5!<%S%9$O!"public ServiceTemplate(ServiceID serviceID, Class[] serviceTypes, Entry[] attrSetTemplates)$B%5!<%S%9(B($B%*%V%8%'%/%H(B)$B$NC5$7J}(B
import java.rmi.*; import net.jini.core.discovery.*; import net.jini.core.lookup.*; public class Bat { public Ball ball; public void play(RemoteBall ball) { try { ball.hit(); System.out.println("I hit the ball"); } catch (RemoteException e) { System.out.println(e); } } public static void main (String[] args) { Bat bat = new Bat(); try { System.setSecurityManager(new RMISecurityManager()); LookupLocator locator = new LookupLocator("jini://localhost"); ServiceRegistrar registrar = locator.getRegistrar(); Class[] classes = new Class[] { RemoteBall.class }; ServiceTemplate template = new ServiceTemplate( null, classes, null); RemoteBall remoteBall = (RemoteBall) registrar.lookup(template); bat.play(remoteBall); } catch (Exception e) { e.printStackTrace(); } } }
$B?.Mj@-$,Dc$$%M%C%H%o!<%/$H!"$I$&@o$&J}K!$N#1$D!#(B
lease $B$K$O!"4|8B$,$"$k!#(B
$B4|8B$ND9$5$O!"8r>D2DG=!#(B $B4|8B$,C;$$(B(1$BJ,0J2
$B%j!<%9$NMxE@(B
Jini $B$N%5!<%S%9$rDs6!$7$F$$$k%*%V%8%'%/%H$O!"(BLease $B%$%s%?%U%'!<%9$r
public interface Lease { long FOREVER = Long.MAX_VALUE; ... long getExpiration(); void renew(long duration) throws LeaseDeniedException, UnknownLeaseException, RemoteException; void cancel() throws UnknownLeaseException, RemoteException; ... }getExpiration() $B$G!"%j!<%9$N;D$j;~4V$,$o$+$k!#%_%jICC10L!#(B
renew() $B$G1dD9$9$k!#(B $B1dD9$G$-$J$$;~$K$O!"(BLeaseDeniedException $B$,JV$5$l$k!#(B
$B$b$&;H$o$J$/$J$C$?;~$K$O!"(Bcancel() $B$G$-$k!#(B $B4|8B@Z$l$HF1$8$3$H$K$J$k!#(B
$B%j!<%9$N4IM}$K$O!"(BLeaseRenewalManager $B$r;H$&!#(B
The following sentences describe the Actor models. Write "Yes" at the beginning of each sentence if it is correct. Write "No" at the beginning of each sentence if it is incorrect.
While a language processing system of Prolog executes a program sequentially, we can consider that we run the program in parallel. The program quicksort includes AND parallelism and OR parallelism. Show a place where AND parallelism exists. Show a place where OR parallelism exists.
The Jini technology uses the idea of leasing. Describe its reason by using an example.