$BJB9T%W%m%0%i%_%s%08@8l(B(1)/Concurrent Programming Languages(1)

$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-2020/2020-06-19
$B$"$k$$$O!" http://www.cs.tsukuba.ac.jp/~yas/cs/
http://www.cs.tsukuba.ac.jp/~yas/

$B"#:#F|$N=EMW$JOC(B

$B;29MJ88%(B References

$B"#(BConcurrent Pascal

5$B7n(B8$BF|$N:F7G(B $BC`
  • $B%W%m%;%9!J%9%l%C%I!K(Ba process (== a thread)
  • $B%b%K%?(B(monitor)$B!#%W%m%;%94V$NF14|IU$-$N%G!<%?9=B$!#(B a data structure with mutual exclusion. $B>r7oJQ?t$H%-%e!<4^$`!#(Bwith condition variables and queues.
  • $B%/%i%9(B(class)$B!#%3!<%I$r

    $B"!;29MJ88%(B references

    Per Brinch Hansen: "The Architecture of Concurrent Program", Prentice Hall (1977).

    Per Brinch Hansen$BCx(B, $BEDCf1QI'Lu(B: "$BJB9TF0:n%W%m%0%i%`$N9=B$(B", $BF|K\%3%s(B $B%T%e!<%?6(2q(B (1980).

    Per Brinch Hansen: "The programming language Concurrent Pascal," IEEE Transactions on Software Engineering, Vol.SE-1, No.2, pp.199-207, June 1975.

    $B"!%W%m%;%9(B process

    $B%W%m%;%9$O!"%G!<%?7?(B(data type)$B$H$7$FDj5A!#(B $BJQ?t$,%$%s%9%?%s%9!#FbIt$KL58B%k!<%W(B(infinite loop)
    type procA_t = process(args...);
       var
          local variables...
       procedure proc1(args...);
       procedure proc2(args...);
    begin
       cycle
           ...
       end;
    end
    
    var procA1 : procA_t ;
    init procA1(args...);
    

    $B"!%b%K%?(B monitor

    $B%b%K%?$O!"%W%m%;%94V$G6&M-$5$l$k%G!<%?9=B$!#(B a monitor is a shared data structure among processes.
    type monA_t = monitor(args $B!&!&!&(B);
       var
          loal variables
       procedure entry proc1(args $B!&!&!&(B);
       procedure entry proc2(args $B!&!&!&(B);
    begin
       initialization of local variables;
    end
    
    var monA1 : monA_t ;
    init monA1($B0z?t(B);
    
    $B%m!<%+%kJQ?t$O!"(Bentry $B$N$N%W%m%;%9$OF~$l$J$$(B(mutual exclusion)$B!#(B

    $B?^(B? $B%W%m%;%9(B3$B8D!

    $B?^(B? Concurrent Pascal$B$N%W%m%;%9$H%b%K%?(B/Processes and a monitor in Concurrent Pascal

    $B"!>r7oJQ?t$H%-%e!<(B condition variable and queue

      cv1 : condition;
      cv1.wait;      $B8F$S=P$7$?%W%m%;%9$rBT$?$;$k!#(Bblock the current process.
      cv1.signal;   $BBT$C$F$$$k%W%m%;%9$,$$$l$PA4$F:F3+$5$;$k!#(Bunblock all waiting processes.
    
      q1 : queue;
      delay(q1);      $B8F$S=P$7$?%W%m%;%9$r$=$N%-%e!<$GBT$?$;$k!#(B
                      block the current process.
      continue(q1);   $B$=$N%-%e!<$GBT$C$F$$$k%W%m%;%9$,$$$l$P#1$D$@$1:F3+$5$;$k!#(B
                      unblock a single process in the queue.
    
    • $BN>J}$H$b!"%b%K%?$NCf$G%W%m%;%9$r%9%j!<%W(B(sleep/block)$B$5$;$k$?$a$K;H$&!#(B
    • $B%W%m%;%9$,%9%j!<%W$7$F$$$k4V$O!"B>$N%W%m%;%9$,(Bentry $B$+$iF~$l$k!#(B
    • signal/continue $B$5$l$k$H!"%W%m%;%9$O!"5/$-$k(B(wakeup/unblock)$B$5$l$k(B $B$,!"(Bentry $B$N(Bprocedure $B$,(B return $B$7$?8e$G!"(B($B$=$N$&$A(B)$B%W%m%;%9$,F0$-=P$9!#(B
    $B:G6a$N8@8l(B(Pthread, Java $BEy(B)$B$G$O!"(BConcurrent Pascal $B$N(B condition variable $B$b(Bqueue$B!!$b!"$H$b$K>r7oJQ?t!#(B

    $B"!M-8B%P%C%U%!(B bounded buffer

    Unix $B$N%Q%$%W(B(pipe)$B$N$h$&$J$3$H$r(B Concurrent Pascal $B$N%W%m%;%9!J%9%l%C%I!K$r;H$C$F $ producer | consumer [$B $B#2$D$N%9%l%C%I$N4V$K$O!"%P%C%U%!$rCV$/!#(B

    $B?^(B? $B4D>u%P%C%U%!(B($BM-8B%P%C%U%!(B)$B!CHq

    $B?^(B? $BM-8B%P%C%U%!(B($B4D>u%P%C%U%!(B)$B!"@8;:CHq

    $B%P%C%U%!$,6u$N;~!"(Bconsumer() $B$O!"(Bproducer() $B$,2?$+%G!<%?$r%P%C(B $B%U%!$KF~$l$k$N$rBT$D!#%P%C%U%!$,$$$C$Q$$$N;~!"(Bproducer() $B$O!"(B consumer() $B$,%P%C%U%!$+$i2?$+%G!<%?$r

    $B

  • put(x:integer): add an integer to the buffer
  • get(result x:integer); remove an integer from the buffer $BDj?t$HJQ?t(B Constants and variables
       1: const BUFFER_SIZE = 4;
       2: type circular_buffer =
       3: monitor
       4: var
       5:     rp : integer ;
       6:     wp : integer ;
       7:     data: array [0..BUFFER_SIZE-1] of integer;
       8:     used: integer;
       9:     not_empty : condition;
      10:     not_full  : condition;
      11: 
      12:     procedure entry put(x:integer);
      13:     begin
      14:         while( used = BUFFER_SIZE ) do
      15:             non_full.wait;
      16:         data[wp] := x;
      17:         wp := wp + 1 ;
      18:         if( wp >= BUFFER_SIZE )
      19:             wp := 0 ;
      20:         used := used + 1 ;
      21:         not_empty.signal;
      22:     end
      23: 
      24:     procedure entry get(result x:integer);
      25:     begin
      26:         while( used = 0 ) then
      27:             not_empty.wait;
      28:         x := data[rp];
      29:         rp := rp + 1 ;
      30:         if( rp >= BUFFER_SIZE )
      31:             rp := 0 ;
      32:         used := used - 1 ;
      33:         not_full.signal;
      34:     end
      35: begin
      36:     rp := 0 ;
      37:     wp := 0 ;
      38:     used := 0 ;
      39: end;
      40: 
      41: ...
      42: var buf : circular_buffer ;
      43: init buf;
      44: ...
      45: 
    

    $B"#(BCommunicating Sequential Processes

    C. A. R. Hoare: "Communicating sequential processes", Communications of the ACM, Volume 21 , No.8 pp.666-677, 1978. https://dl.acm.org/citation.cfm?doid=359576.359585

    $B652J=q(B C. A. R. Hoare: "Communicating Sequential Processes", Prentice-hall International, 1985. [PDF(2015)]

    $B"!(BCSP$B$NDL?.$H%W%m%;%9(B/Communication and processes in CSP

    $BD>@\L>A0IU$1$NDL?.(B(direct naming)$B!#DL?.Aj

    Process A:

    ...
    B ? x;   -- $B%W%m%;%9(B B $B$+$i$NDL?.$rBT$D!#(B Wait for a message from Process B.
             -- $B%a%C%;!<%8$r
    
    

    Process B:

    ...
    y := 5;
    A ! y + 1; -- $B%W%m%;%9(B A $B$XCM(B 6 $B$rAw$k!#(BSend the value 6 to Process A.
    ...
    A ? y;     -- $B%W%m%;%9(B A $B$+$i$NDL?.$rBT$D!#(BWait for a message from Process A.
               -- $B%a%C%;!<%8$r
    
    

    $B%W%m%;%9$r;XDj$9$kL>A0IU$1$G$O!"%i%$%V%i%j$,:n$l$J$$!#%^%/%m$G$4$^$+$9!#(B

    $B"!@)8f9=B$!"%,!<%IIU$-%3%^%s%I!"Hs7hDj@-(B

    $B%,!<%I(B(guard) $B"*(B $B%3%^%s%I(B(command)
    $B%,!<%IIU$-%3%^%s%I!#>r7o<0!#(B $B!V"*!W$N:8$,$9$Y$F??$J$i!"!V"*!W$N1&$r * [ <test> $B"*(B <action> ]
    $B7+$jJV$7!#(Bwhile test do action <test>$B$NItJ,$O!"%,!<%I(B(guard)$B$H8F$P$l$k!#(B $B%,!<%I$K$O!"C1=c$J>r7o<0$NB>$K!"F~NO!J $BL>A0(B::...
    $B%W%m%;%9$NL>A0IU$1!#(B
    ||
    $BJB9T $B""(B$B!!(B($B@5J}7A$G$O$J$/!"=DD9$K=q$/$N$,@53N!#!V(B▯ $B!W$N$h$&$J46$8!#(B)
    alternative command$B!#Hs7hDj@-$N5-=R!#(B
    name ( val1, val2 )
    $B9=B$BN$NDj5A!#(Bname $B$,9=B$BN$NL>A0!#(Bval1, val2 $B$OCM!#(B $B%U%#!<%k%I$K$OL>A0$,$D$1$i$l$J$$!#(B
    (x,y) := (y,x)
    $BL>A0$,$J$$9=B$BN$NBeF~!#(B $BJB9T$K $B%^%/%mL>(B $B-q(B $BK\BN(B
    $B%^%/%mDj5A!#(B
    $B%W%m%;%9$NG[Ns(B P(1..n)
    $B0UL#$H$7$F$O!"%W%m%;%9$,%^%/%mE83+$5$l$k!#(B $B%W%m%;%9$OE:;z$G6hJL$5$l$k!#(B

    $B"!%^!<%8!&%W%m%;%9(B/A merge process in CSP

    $B%^!<%8!&%W%m%;%9$NNc!#%W%m%;%9(BX, Y, Z$B$N$$$:$l$+$+$iAw$i$l$F$-$?%a%C%;!<(B $B%8$r Merge:: c:character; *[ $B!!(B X ? c $B"*(B Sink ! c $B""(B Y ? c $B"*(B Sink ! c $B""(B Z ? c $B"*(B Sink ! c ]

    $B?^(B? $B%W%m%;%9(B5$B8D!

    $B?^(B? CSP$B$K$h$k%^!<%8!&%W%m%;%9(B/A merge process in CSP

    $B$b$7Hs7hDj@-$,$J$1$l$P!"I,$:(B X, Y, Z, X, Y, Z, ... $B$H7+$jJV$9!#(B
    Merge:: c:character;
            *[  X ? c $B"*(B Sink ! c;
                Y ? c $B"*(B Sink ! c;
                Z ? c $B"*(B Sink ! c ]
    

    $B"!M-8B%P%C%U%!(B/bounded buffer in CSP

       1: [ Buffer::
       2:     buf(0..bufsize-1): buffer_element;
       3:     first, last : integer;
       4:     j,k         : integer;
       5:     first :=0;
       6:     last :=0;
       7:     * [ (j: 1..numprod)
       8:         (last + 1) mod bufsize $B!b(B first;
       9:         Producer(j) ? buf(last) $B"*(B
      10:             last := (last +1) mod bufsize
      11:         $B""(B
      12:         (k: 1..numcons)
      13:         first $B!b(B last;
      14:         Consumer(k) ? more() $B"*(B
      15:             Consumer(k) ! buf(first);
      16:             first := (first + 1) mod bufsize
      17:       ]
      18: || (i:1..numprod) PRODUCER -- $B@8;:CHq
    
    
    
    

    $B"!;EMM$HK\BN(B/specification and body

    Ada$B$O!"%+%W%;%k2=$r=E;k$7$?@_7W$K$J$C$F$$$k!#(B
    $B;EMM(B(specification)
    $B%$%s%?%U%'!<%9$N5-=R(B(interface description)$B!#%W%m%0%i%`$NB>$NMWAG(B $B$+$i;2>H$G$-$k!#;EMM$@$1$o$+$l$P!"J,3d%3%s%Q%$%k$G$-$k!#(B
    $BK\BN(B(body)
    $B%W%m%0%i%`$N%3!<%I!"JQ?t$J$I!#(B

    $B"!%(%s%H%j(B/entries

    $B%W%m%;%94VDL?.!J%?%9%/4VDL?.!K$Nl=j$K(Baccept $BJ8$r5-=R$9$k!#(B

    $B;EMM$NNc!##19T$N%P%C%U%!!#(B

    task line_block is
        entry add( c: in character);
    end  line_block;
    
    in $B$O!"F~NO%Q%i%a%?$N0UL#!#%?%9%/B&$+$i8+$FF~NO!J

    $B accept add( c: in character) do thisline(i) := c; end add; // i := i + 1;

    $B8F=P$7B&$NNc(B

        line_block.add("d");
    
    $B%(%s%H%j$r8F$S=P$9$H!"8F$S=P$7$?%?%9%/$O!"%V%m%C%/$5$l$k!#(B $B$B"!%i%s%G%V(B/Rendezvous

    $B%W%m%;%9(B1$B!

    $B?^(B? $BBP>NE*$J%i%s%G%V(B/ Symmetric rendezvous

    $B8F=P$7B&!

    $B?^(B? Ada$B$N%i%s%G%V(B/ Rendezvous in Ada

    • $B%i%s%G%V$O!"#2$D$N%?%9%/$,6&$KJB$s$G Ada$B$N%i%s%G%V$O!"Aj8_GS=|$KMxMQ$5$l$k!#%i%s%G%VCf$O!":]$I$$NN0h(B (critical section)$B$G$"$j!"#1$D$N%?%9%/$7$+F0$+$J$$!#(B

    $B"!(Bselect$BJ8(B/select statement

    CSP $B%,!<%IIU$-%3%^%s%I$H!V""!W$N(B Ada $BHG!#(B
    select
        when  Cond =>
            accept ... do ... end;
    or
        when  Cond =>
            accept ... do ... end;
    or
        when  Cond =>
            delay seconds;
    end
    
    • $B!V(Bwhen Cond =>$B!W$O!"=q$+$J$/$F$b$h$$!#(B
    • accept $BJ8$NBe$o$j$K!"(Bdelay $BJ8(B($B;~4V@Z$l5-=R(B)$B$b=q$1$k!#(B
    • else $B$G!"2?$bA*$P$l$J$$;~$NF0:n$,=q$1$k!#(B
    $B3+$$$F$$$k%(%s%H%j(B
    when $B$N(B Cond $B$,??(B
    $BJD$8$F$$$k%(%s%H%j(B
    when $B$N(B Cond $B$,56(B

    $B"!%i%$%s%W%j%s%?$N%P%C%U%!(B/a buffer in a line printer

    • $B%(%s%H%j(B add() $B$G!"J8;z$r 120$BJ8;zN/$a$F%W%j%s%?$KAw$k!#(B
    • $B%W%j%s%?$,0u:~Cf$G
         1: type line is array (1..120) of character;
         2: 
         3: task line_block is
         4:     entry add( c: in character);
         5:     entry please_print( ln: out line);
         6: end  line_block;
         7: 
         8: task body line_block is
         9:     printer_trouble_time  : constant integer := 300;
        10:     print_line, fill_line : line;
        11:     nextfree              : integer;
        12:     print_ready           : boolean;
        13: begin
        14:     nextfree    := 1;
        15:     print_ready := false;
        16:     loop
        17:         select
        18:             when (nextfree < 121 ) =>
        19:                 accept add( c: in character) do
        20:                     fill_line(nextfree) := c;
        21:                 end add;
        22:                 nextfree := nextfree + 1;
        23:                 if( next_free = 121 ) and not print_ready then
        24:                     print_ready := true;
        25:                     nextfree    := 1;
        26:                     print_line  := fill_line;
        27:                 end if;
        28:         or
        29:             when print_ready =>
        30:                 accept please_print( ln: out line ) do
        31:                     ln := print_line;
        32:                 end please_print;
        33:                 if nextfree = 121 then
        34:                     print_line := fill_line;
        35:                     nextfree   := 1;
        36:                 else
        37:                     print_ready := false;
        38:                 end if;
        39:         or
        40:             when print_ready and (nextfree > 120) =>
        41:                 delay printr_trouble_time;
        42:                     printer_trouble;
        43:         end select;
        44:     end loop;
        45: end line_block;
      

      $B"#J,;67?%W%m%0%i%_%s%08@8l0lHLO@(B/Distributed programming languages -- general ideas

      $B%W%m%0%i%_%s%08@8l$O!"%M%C%H%o!<%/$NB8:_$dDL?.$r$5$^$6$^$JEY9g$$$G1#$7$F$$$k!#(B A programming language hides underlying networks and communication in a degree.

      $BLdBj(B Question:

      • $B$I$3$^$G1#$;$PJ,;67?%W%m%0%i%_%s%08@8l$H8F$s$G$b$h$$$+!)(B How strongly should a distributed programming language hide underlying networks?
      $B!V(Bsocket $B$,$"$l$P!"J,;67?%W%m%0%i%_%s%08@8l!W$H$O!"Dj5A$7$?$/$J$$!#(B

      $B"!J,;67?#O#S$H%M%C%H%o!<%/#O#S(B/distributed operating systems and network operating systems

      $B%M%C%H%o!<%/!&%*%Z%l!<%F%#%s%0!&%7%9%F%`(B a network operating system

      $B%M%C%H%o!<%/$N5!G=$O$"$k!#(Bhas a networking facility.

      $BMxMQo$K$I$N7W;;5!$r;H$C$F$$$k$N$+$r0U<1$9$kI,MW$,$"$k!#(B A user is aware of which computer in a network he/she is using.

      $B%3%^%s%I(B commands

      • sh <-> ssh (rsh)
      • cp <-> scp (rcp)
      • ls, less <-> WWW browsers
      $B%7%9%F%`%3!<%k(B system calls
      • pipe <-> socket
      • /../host1/usr/local/bin ($B%9!<%Q!<%G%#%l%/%H%j(B(super directory))

      $BJ,;67?%*%Z%l!<%F%#%s%0!&%7%9%F%`(B a distributed operating system

      $BMxMQA[E*$J#1Bf$N=8Cf7?7W;;5!$r;H$C$F$$$k$h$&$K46$8!"7W;;5!$H7W;;5!$N(B $B6-3&@~$,8+$($J$/$J$k!#J,;6F)L@@-!J(Bnetwork transparency$B!K$,

      $BL\I8(B goals

      • $B=8Cf7?%7%9%F%`$G3+H/$5$l$?%W%m%0%i%`$r0l@ZJQ99$9$k$3$H$J$/!"%M%C(B $B%H%o!<%/>e$N;q8;$rMxMQ$9$k$3$H$,$G$-$k$h$&$K$J$k!#(B Run applications for centralized systems in a distributed system without any modifications to the applications.
      • $B%U%)!<%k%H!&%H%l%i%s%9!#>c32$,H/@8$7$?$H$7$F$b!"<+F0E*$KI|5l$5$;(B $B$?$j!"<+F0E*$KB>$N7W;;5!$K;E;v$r2s$9!#(B
      • $BIi2Y6Q9U(B(load balncing)$B!#%W%m%0%i%`$rAv$i$;$k$H!"<+F0E*$K6u$$$F$$(B $B$k7W;;5!$KAw$i$l!" $B8=:_$N5;=Q(B current technologies
        • NFS$B!#%M%C%H%o!<%/!&%U%!%$%k!&%7%9%F%`!#(B $BJ,;67?%U%!%$%k%7%9%F%`$G$O$J$$!#(B Network File System (NFS) by Sun. Not a distributed file system.
        • NIS, LDAP$B!#%Q%9%o!<%I!&%U%!%$%k$N6&M-!#(B Sharing of a password file.

        $BCm0U(B: $BIi2YJ,;6$NJ,;6(B(load sharing/balancing)$B$H$3$N9V5A$N%?%$%H%k$NJ,;6(B (distributed)$B$O0UL#$,0c$&!#(B

        $B"!%m!<%+%k$H%j%b!<%H$NE}9g(B/Unifying local and remote

        A note on Distributed Computing [Waldo 1994]

        • $B8F=P$7$,%m!<%+%k$G$b%j%b!<%H$G$b!V7A<0E*$J@5$7$5!W$OF1$8!#(B $B%*%V%8%'%/%H$N0LCV$O!"%W%m%0%i%`$N@5$7$5$K$O1F6A$7$J$$!#(B
        • $B%*%V%8%'%/%H$N%$%s%?%U%'!<%9$O!"%*%V%8%'%/%H$,;H$o$l$k%3%s%F%-%9(B $B%H$+$iFHN)$7$F$$$k!#(B
        • $BJ,;6%"%W%j%1!<%7%g%s$O!"%m!<%+%k%"%W%j%1!<%7%g%s$HF1$8J}K!$G(B $B $B8N>c$d@-G=$NB&LL$r9M$($kI,MW$,$"$k!#!J=i4|CJ3,$G$O9M$($J$/$F$b$h$$!#!K(B
        $B$3$NJ}K!O@$K$=$C$F3+H/$5$l$?%W%m%0%i%_%s%08@8l$b$"$k$,!"(B $B$=$N$h$&$J8@8l$N%"%W%j%1!<%7%g%s$NHO0O$O69$$!#(B

        $B"!%m!<%+%k$N%W%m%0%i%_%s%0$HJ,;6$N%W%m%0%i%_%s%0$N0c$$(B/local programming and distributed programming

        $BNr;K(B history
        • 1970$BG/Be!#(Bsocket()$B!#(BCSP$B!"(BOccam$B!#(B
        • 1980$BG/Be!#(BRPC$B!#(B
        • 1990$BG/Be!#(BORB$B!#(B
        • 2000$BG/Be!#%3%s%]!<%M%s%H!#(BComponents, XML Web Services, REST, Ajax
        $BC1$K7R$0$@$1$G$O!"J,;6$NFq$7$$LdBj$O!"2r7h$5$l$J$$!#(B

        $B"!J,;6$NFq$7$$LdBj(B/Issues in distributed systems

        $BNc(B:

        • $BItJ,E*$KMn$A$F$$$k(B(partial failure)
        • $B%l%$%F%s%7!#8w$NB.EY$O1[$($i$l$J$$!#(Blatency$B!#(B
        • $B;2>H!#%]%$%s%?$r$I$&$9$k$+!#(BReferences$B!#(B
        • $BJB9T@-!#(BConcurrency$B!#(B
          • $BHs7hDj@-$N07$$(B nondeterminism
          • $BF14|$NFq$7$5(B synchronization

        $B"!(BRMI$BIU(BJava$B$O!"J,;67?%W%m%0%i%_%s%08@8l$+(B/Is the Java language with RMI a distributed programming language?

        • public $B$7$+8F$Y$J$$!#(B
        • $B%*%V%8%'%/%H!&%^%$%0%l!<%7%g%s$O$J$$!#(BNo object migration
        • $B%j%b!<%H$N%3%s%9%H%i%/%?$,8F$Y$J$$!#L>A0%5!<%S%9$rDL$8$F%"%/%;%9(B $B$9$k!#(Bfactory object ($B%*%V%8%'%/%H$r@8@.$9$k%*%V%8%'%/%H(B)$B$r;H$($P$h$$(B $B$,!"%m!<%+%k$H%j%b!<%H$NF)L@@-$O2<$,$C$F$$$k!#(B No remote constructor.
        • $BHsF14|E*$J8F=P$7$O$G$-$J$$!#%9%l%C%I$G%(%_%e%l!<%H2DG=$G$O$"$k!#(B $BI8=`$GJBNs@-$,$^$C$?$/=P$J$$!#(B No asynchronous invocation in standard (without threads).

        $B"!J,;67?%W%m%0%i%_%s%08@8l$NMW7o(B/Requirements of distributed programming languages

        1. $B0LCV$H7?$ND>9T!#(Blocation-type orthogonal
        2. $B1s3V%*%V%8%'%/%H@8@.!#(BRemote object creation
        3. $B%m!<%+%k$H%j%b!<%H$r6hJL$7$?$$;~$K$O6hJL$G$-$k!#(B We can distinguish a local object from a remote object when we want to do that.
        4. $B%m!<%+%k$H%j%b!<%H$r6hJL$7$?$/$J$$;~$K$O6hJL$7$J$$$G$h$$!#(B We do not have to distinguish a local object from a remote object when we do not want to do that.
        5. Garbage colection
        6. $B%*%V%8%'%/%H!&%^%$%0%l!<%7%g%s!#(BObject migration$B!#(B
        7. $B%0%k!<%W2=!#(BGrouping
        8. $BF14|8F=P$7$HHsF14|8F=P$7$NN>J}$N;Y1g!#(BSupport for synchronous and asynchronous calling
        9. $BJ,;6$G$b!"JB9T@-$r8@8l$G;Y1g$7$?$$!#(BSupport for concurrency$B!#(B

        $BJ,;6$NFq$7$$LdBj$O!"$^$@HFMQE*$K2r$1$k5;=Q$O$J$$!#(B $BHFMQ@-$,$J$$$H!"%W%m%0%i%_%s%08@8l$K$O:N$jF~$l$K$/$$!#(B

        $B"!J,;67?(BOS$B$HJ,;67?%W%m%0%i%_%s%08@8l(B/a distributed operating system and a distributed programming language

        $BJ,;6#O#S>e$GJ,;6%7%9%F%`$,Av$k$+!#(B Can a system written in a distributed programming language run in a distributed operating system?

        $B"#(BEmerald

        $B=i4|(B(1980$BG/Be(B)$B$NJ,;67?8@8l!#%*%V%8%'%/%H;X8~!#(B Emerald is an early distributed object-oriented language.

        $B0lHLE*$JFCD'(B

        • $B=c?h$J%*%V%8%'%/%H;X8~!#A4$F$N%G!<%?7?!"9=B$BN$,%*%V%8%'%/%H!#(B
        • $B6/$$7?IU$1!#(Babstract type ($B%$%s%?%U%'!<%9(B)
        • $BF0E*$J%*%V%8%'%/%H$NDI2C$,2DG=!#(B
        • $BB?BV(B(polymorphism)
        • $B%/%i%9$O$J$$!#7Q>5$b$J$$!#

          Emerald $B$NL\I8!#(B

          • $BJ,;6F)L@@-!#%a%=%C%I8F=P$7$O!"%m!<%+%k$H%j%b!<%H$GF1$8!#(B
          • $B%*%V%8%'%/%H%l%Y%k$N0\F0@-!#(B $B%*%V%8%'%/%H$O!"$$$D$G$b(B $B%3%s%T%e!<%?$N6-3&$r1[$($F0\F02DG=$G$"$k!#(B $B%*%V%8%'%/%H$,<+J,<+?H$r0\F0(B(migrate)$B$5$;$k$3$H$,$"$k!#(B
          • $B8zN(!#%m!<%+%k!&%*%V%8%'%/%H$X$N%"%/%;%9$O!"(B($BJ,;6$G$O$J$$8@8l$HF1(B $B$8$h$&$K(B)$B2DG=$J8B$jD>@\E*$K8zN($h$/9T$o$l$k!#%M%C%H%o!<%/DL?.$J$7$K%m!<(B $B%+%k$N8F=P$7$+%j%b!<%H$N8F=P$7$+$r7h$a$i$l$k!#(B
          $BJ,;6F)L@@-$H0\F0$O!"L7=b$7$F$$$k!#(B

          $B"!(BEmerald$B$N;2>H(B/Refrences in Emerald

          Emerald $B$G$O!"%*%V%8%'%/%H$N%"%/%;%9$O!";2>H(B(reference)$B$rDL$8$F9T$o$l(B $B$k!#;2>H$O!"%m!<%+%k$b%j%b!<%H$b6hJL$,$J$$!#(B ($BJ,;6F)L@@-$,

          $B%a%=%C%I8F=P$7$N0z?t$b;2>H$GEO$5$l$k!#%*%V%8%'%/%H$N>l=j$,0c$&$H!"=E$?(B $B$$!#%3%T!<$NJ}$,B.$$!#(B

          $B"!(BEmerald$B$N%*%V%8%'%/%H!&%^%$%0%l!<%7%g%s(B/ Object migration in Emerald

          Emerald $B$K$O8zN($r5s$2$k$?$a$K!"%*%V%8%'%/%H$r0\F0(B(migrate)$B$5$;$k5!G=(B $B$,$"$k!#(B
          move X to Y
          $B%*%V%8%'%/%H(B X $B$r!"%*%V%8%'%/%H(B Y $B$N$"$k%[%9%H$K0\F0!#%R%s%H(B ($B%7%9%F%`$O fix X at Y
          $B%*%V%8%'%/%H(B X $B$r!"%*%V%8%'%/%H(B Y $B$N$"$k%[%9%H$K0\F0$7$F!"(B $B$5$i$KF0$+$J$$$h$&$K8GDj$9$k!#(B
          unfix X
          $B%*%V%8%'%/%H(B X $B$r!":F$S0\F02DG=$K$9$k!#(B
          refix X at Z
          fix $B$5$l$F$$$k%*%V%8%'%/%H(B X $B$r!"%*%V%8%'%/%H(B Z $B$N$"$k%[%9%H$K0\(B $BF0$7$F!"$5$i$KF0$+$J$$$h$&$K8GDj$9$k!#A4BN$,(B atomic $B$K9T$o$l$k!#(B

          Call by reference $B$,=E$?$$!#(B

          call by move
          $B0z?t$r%*%V%8%'%/%H$NJ}$K0\F0$5$;$k!#(B
          call by visit
          $B%a%=%C%I$,%j%?!<%s$9$k$H!"%*%V%8%'%/%H$bLa$C$F$/$k!#(B
          call by move return
          $B7k2L$N%*%V%8%'%/%H$bLa$C$F$/$k!#(B
          $B0\F0$NN3EY$,=EMW!#%*%V%8%'%/%H$N%0%k!<%W2=!#(B attached $B%-!<%o!<%I$,$D$$$F$$$k$H!"$$$C$7$g$K0\F0$9$k!#(B

          $B"#(BVoyager

          Glue $B$N(B Graham Glass $B$h$j:n@.$5$l$?(BJava $BMQ$NJ,;6%*%V%8%'%/%H!#(B(Voyager $B$NJ}$,8E$$!#(B)

          • $B1s3V$K%*%V%8%'%/%H$N@8@.$,$G$-$k!#(BFactory.create()$B!#(B Remote object creation.
          • (Glue$BF1MM$K(B) $BL>A0$,$D$$$?%*%V%8%'%/%H$r(B $B%"%/%;%9$b$G$-$k!#(BNamespace.lookup()$B!#(B Naming a remote object like Glue.
          • $BJ,;6(BGC$B$r4^$`!#(B Support distributed garbage collection.
          • $B%*%V%8%'%/%H$N0\F0$,$G$-$k!#<+J,<+?H$N0\F0$b$G$-$k!#(B Support object migration.
          • $B%"%W%l%C%H4VDL?.DL?.$r;Y1g!#(Bvoyager $B$,%O%V$K$J$k!#(B Inter-applet communication through a voyager server.
          • $B%^%k%A%-%c%9%H$,$G$-$k!#(B Support multcast.
          • $B%*%V%8%'%/%H$r%a%b%j$+$iDI$$=P$7$F%G!<%?%Y!<%9$KJ]B8$G$-$k!#(B Support persistent objects.
          • CORBA, DCOM, RMI $B$H$b$D$J$,$k!#(B Interoperable with CORBA, DCOM, and RMI objects.
          • 2001 $BG/!"(BObjectSpace $Bhttp://www.recursionsw.com/products/voyager/voyager-intro.html

          $B"!(BInterface and local objects

          import com.objectspace.voyager.*;
          
          public interface IBall {
          
                 public void hit();
          
          }
          
          import com.objectspace.voyager.*;
          
          public class Ball implements IBall {
          
          	public void hit() {
          		System.out.println("Ball has been hit");
              }
          }
          

          $B"!(BVoyager$B$N%*%V%8%'%/%H$N8x3+(B/Publishing objects in Voyager

          
          import com.objectspace.voyager.*;
          
          public class BallMachine  {
          
              public static void main(String[] args) {
          		try {
          			Voyager.startup("8000"); // als Server starten
          			Ball ball = new Ball();
          			Namespace.bind("EinBall",ball);
          		} catch( Exception exception ) {
          			System.err.println( exception );
          		}
              }
          }
          

          $B"!(BVoyager$B$N%*%V%8%'%/%H$NMxMQ(B/Using remote objects in Voyager

          import com.objectspace.voyager.*;
          
          public class Bat {
          
              public void play(IBall ball) {
          		System.out.println("Hitting the new Ball");
          		ball.hit();
              }
          
              public static void main(String[] args) {
          		try {
          		    Voyager.startup(); // als Client starten
          			Bat bat = new Bat();
          			IBall ball = (IBall) Namespace.lookup("//vsyspc5.informatik.uni-hamburg.de:8000/EinBall");
          			bat.play(ball);
          		} catch( Exception exception ) {
          			System.err.println( exception );
          		}
          		Voyager.shutdown();
              }  
          }
          

          $B"!(BVoyager$B$N%j%b!<%H!&%j%U%!%l%s%9$H0\F0(B/ Remote references and object migration in Voyager

          Proxy.of(obj) $B$G!"%j%b!<%H%j%U%!%l%s%9$r@8@.$9$k!#(B Mobility.of(obj)$B$G!"0\F02DG=$J%*%V%8%'%/%H$rF0E*$K@8@.$9$k!#(B

              IMobility mobileObj = Momility.of(obj);
              mobileObj.moveTo("url");
          
          
          import com.objectspace.voyager.*;
          import com.objectspace.voyager.mobility.*;
          
          public class Bat {
          
             public void play(IBall ball, String url) {
          	  try {
          		 ball.hit();
          		 System.out.println("Ball bewegen?");
          		 Mobility.of(ball).moveTo(url);
          		 System.out.println("Ball bewegt");
          	  } catch (MobilityException e) {
          		 System.out.println(e);
          		 e.printStackTrace();
          	  }
             }
          
             public static void main(String[] args) {
                try {
          		 Voyager.startup("9001"); 
          		 ClassManager.enableResourceServer();
          		 Bat bat = new Bat();
          		 //Ball newball= new Ball();
          		 IBall ball = (IBall) Proxy.of(new Ball());
          		 bat.play(ball,"//vsyspc5:8000");
          		 System.out.println("Ball 1ste mal gespielt");
          		 bat.play(ball,"//localhost:9001");
                } catch( Exception exception ) {
          	    System.err.println( exception );
                }
                Voyager.shutdown();
             }
          }
          

          $B"!(BVoyager$B$N%j%b!<%H!&%3%s%9%H%i%/%?(B/A Remote constructor in Voyager

              IA a1 = (IA) Factory.create("A","//sun:8000");
          

          $B"!(BVoyager$B$NHsF14|%a%=%C%I8F=P$7(B/Asynchronous object invocation

          $BHsF14|%a%=%C%I8F=P$7$,$"$k!#(B

              IA a1 = (IA) Factory.create("A","//sun:8000");
              int x = a1.method(param1,param2);  // $BF14|(B synchronous
          
              Result r1 = Future.invoke(a1, "method", // $BHsF14|(B asynchronous
                  new Object [] {param1,param2});
          ...
              if( r1.isAvailable() )
              {
                 int x = r1.readInt();
              }
          
          $B%a%=%C%IL>$rJ8;zNs$GEO$9!#7k2L$H$7$F!"(BResult $B7?$rJV$9!#(BisAvailable() $B%a%=%C%I$G=*N;$rBT$D!#(BreadInt(), readByte(), readObject() $B$G!"(Bint, byte, $B%*%V%8%'%/%H$KLa$9!#(B

          $B"!(BVoyager$B$N%^%k%A%-%c%9%H(B/Multicast in Voyager

          Voyager Space $B$r;H$C$F%^%k%A%-%c%9%H$,$G$-$k!#(B
              A a1 = new A();
              A a2 = new A();
          
              a1.method1( param1, param2 ); // Unicast
              a2.method1( param1, param2 ); // Unicast
          
              ISubspace subspace = (ISubspace) Namespace.lookup("//sun:9000/Subspace");
              subspace.add(a1);
              subspace.add(a2);
              Object [] params = new Object [] { param1, param2 };
              Multicast.invoke(subspace,"method1",params,"A");
          

          $B"#(BDejay

          • $BJ,;6(BJava$B$N#1$D!#%=!<%9!&%W%m%0%i%`0l8+!"(BJava$B$K8+$($k$,!"(BJava$B$G$O$J$$!#(B Java $B$N%3%s%Q%$%i$G$ODL$i$J$$$b$N$,$"$k!#(B Dejay is a distributed Java language. A program in Dejay looks like that in Java, but Dejay has some differences.
          • Dejay $B%3%s%Q%$%i$,=PNO$9$k(B $B%*%V%8%'%/%H!&%3!<%I$H$7$F$O!"(B Java $B$N%P%$%H%3!<%I(B(.class) $B$r;H$&!#(B The Dejay compiler emits Java byte code.
          • $B $B%3%s%Q%$%i$N

            $B"!(BDejay$B$N%*%V%8%'%/%H(B/ Objects in Dejay

            • $B3HD%;R(B .dj$B!#(Bsuffix .dj.
            • $B1s3V$G
              public class Hello implements java.io.Serializable  {
                  public void sayHello(java.lang.String name) {
                      System.out.println("Hello " + name);
                  }
              }
              
              djayc $B%3%s%Q%$%i$G!"#2$D$N(B Java $B$N%/%i%9$,:n$i$l$k!#(B The djayc compiler generates two Java class files.
              • Hello.class
              • DjHello.class (-l $B%*%W%7%g%s(B $B$D$1$k$H!"%m!<%+%k@lMQ$H$J$j!"(B $B@8@.$5$l$J$$(B)

              $B"!(BDejay$B$N5/F0%3!<%I(B/Startup code in Dejay

              	
              import dejay.base.*;
              public class HelloStartup {
                  public static void main(String args[])
                  {
                      try {
              	    DjProcessor p1 = new DjProcessor("//localhost:8000");
              	    DjHello hello1 = new DjHello(p1);
              	    hello1.sayHello("Thorsten");
              	    p1.moveTo("//localhost:9000");
              	    hello1.sayHello("Jan");
              	    hello1.moveTo("//mac:9000");
                      } catch (ConstructProcessorFailedException e) {
                          System.out.println("Creating Virtual Processor failed."+e);
                      }
                  }
              }
              
              • DjHello$B7?(B ($B1s3V;2>H7?(B) $B!#%m!<%+%k$HF1$8$K07$($k$,!"(B $B DjProcessor $B7?!#%*%V%8%'%/%H$r]2=$7$?$b$N!#(B voyager $B%G!<%b%s$r5/F0$7$?%[%9%H!#(B
              • moveTo() $B%a%=%C%I$G0\F0$G$-$k!#(B DjProcessor $BC10L$G$b!"%*%V%8%'%/%HC10L$G$b0\F0$G$-$k!#(B

              $B"!(BDjProcessor

              $B#1$DL\$N2>A[%W%m%;%C%5$O!"0EL[E*$K:n$i$l$k!#(B $B#2$DL\0J9_$O!"L@<(E*$K:n$k!#(B
                  DjProcessor p1 = new DjProcessor("hostname:port");
              
              $B$3$l$K$h$j!"%[%9%H(B hostname $B>e$N(B $B%]!<%HHV9f(B port $B$G?7$?$J(B $B2>A[%W%m%;%C%5$,:n$i$l$k!#(B $B%[%9%H(B hostname $B$G$O!";vA0$K(B Voyager $B%G!<%b%s$rAv$i$;$F$*$/I,MW$,$"$k!#(B

              $B"!1s3V%*%V%8%'%/%H(B/Remote objects

              class A (.dj) $B$+$i!"<+F0E*$K(B $B%9%?%V(B($B%W%m%-%7(B)$B$H$J$k(B class DjA $B$,@8@.$5$l$k!#(B $B%3%s%9%H%i%/%?$N0z?t$,#18DB?$$!#(B
                  DjA a1 = new DjA( A$B$N0z?t!&!&!&(B, DjProcessor );
              
              $B$3$l$G!"1s3V$N2>A[%W%m%;%C%5$G%*%V%8%'%/%H$,@8@.$5$l!"(B $B1s3V;2>H(B(remote reference)$B$,JV$5$l$k!#(B $BDL>o$N;2>H$HF1$8$K$J$k$h$&$K4hD%$C$F$$$k$,!"(B $B0lIt0c$&!#(B

                  DjA a2 ;
                  a2 = ... ;
                  ...
                  if( a2 == a1 ) // $B1s3V$N%*%V%8%'%/%H$G$O$J$/$F%m!<%+%k$N%9%?%V$NHf3S(B
                  {
                     ...
                  }
              
              equals() $B%a%=%C%I$O!"1s3V$G$bF/$/!#(B

              $B%m!<%+%k!&%*%V%8%'%/%H$r0z?t$K$7$F!"(B $B%j%b!<%H!&%*%V%8%'%/%H$r8F$V$H!"<+F0E*$K1s3V$K%3%T!<$,EO$5$l$k!#(B $B!J1s3V%*%V%8%'%/%H$,:n$i$l$F!"1s3V;2>H$,EO$5$l$k$N$G$O$J$$!#!K(B

              DjX $B7?$N%*%V%8%'%/%H$r(B $B1s3V$K%j%?!<%s$9$k$3$H$O$G$-$k!#(B DjX $B$,$_$D$+$i$J$1$l$P!"(B X$B$N%3%T!<$,JV$5$l$k!#(B

              remote.getCopy() $B$G!"%m!<%+%k$N%3%T!<$,F@$i$l$k!#(B

                  DjA a1 = new DjA(p1);
                  A a2 = a1.getCopy();
              

              $B"!%a%=%C%I8F=P$7$N%;%^%s%F%#%/%9(B/Semantics of method invocation

              $B#3$D$N%a%=%C%I8F=P$7$N%;%^%s%F%#%/%9$,$"$k!#(B
                  DjA a1 = new DjA(p1);
                  B b1 = a.method1( 10 );		 // $BF14|!!(B synchronous
                  B b2 = a.method1( 10, Dejay.ASYNC ); // $BHsF14|(B asynchronous
                  a.method1( 10, Dejay.ONEWAY );       // $B0lJ}8~(B one-way
              
              $BHsF14|$K$O!"40N;BT$A$NJ}K!$,#2 B b1 = a.method1( 10, Dejay.ASYNC ); b1.method2(); // wait by nesessity B b2 = a.method1( 10, Dejay.ASYNC ); if( b2.isAvailable() ) { b2.method2(); } else { // do something b2.waitForResult(); b2.method2(); }

    $B"!(BDejay$B$NL>A0%5!<%S%9(B/Name service

    $B%*%V%8%'%/%H$KJ8;zNs$NL>A0$rIU$1$F!"1s3V$+$i%"%/%;%9$G$-$k$h$&$K8x3+$9(B $B$k$3$H$,$G$-$k!#(B

    $B#2%l%Y%k$NL>A0!#(B

    • $B2>A[%W%m%;%C%5$NL>A0(B
    • $B2>A[%W%m%;%C%5Fb$NL>A0(B

        DjProcessor p1 = new DjProcessor("lin:8000");
        p1.registerByName("p1");
        DjA a1 = new DjA(p1);
        a1.registerByName("a1");
    
        DjProcessor p1 = Dejay.getProcessorByName("p1");
        DjA a1 = p1.getObjectByName("a1");
    

    $B"!1JB3@-(B/Persistence

    $BJ,;6$H1JB3$O!"$+$J$j4X78$7$F$$$k!#(B
    • $BJ,;6$,4{$K $B1JB3$,4{$K Dejay $B$G$O!"2>A[%W%m%;%C%5C10L$G1JB3$K$G$-$k!#(B DjProcessor $B$N%3%s%9%H%i%/%?$G!"J8;zNs$NL>A0$H(B $B%G!<%?%Y!<%9$NL>A0$r DjProcessor p1 = new DjProcessor("PersistProc","ProcesssorDB","lin:8000"); DjA a1 = new DjA(p1); if( p1.isPersistable ) { p1.persist(); p1.flush(); } persist() $B$r8F$V$H!"%G!<%?%Y!<%9$KJ]B8$5$l$k!#(B flush() $B$r8F$V$H!"%a%b%j$,(B GC $B$G2s<}2DG=$K$J$k!#(B

      persist() $B$G%G!<%?%Y!<%9$KJ]B8$5$l$?%*%V%8%'%/%H$b!"(B $B;H$o$l$k<+F0E*$K%G!<%?%Y!<%9$+$i2sI|$5$l$k!#(B

      $B2>A[%W%m%;%C%5A4BN$,%G!<%?%Y!<%9$KJ]B8$G$-$k!#(B $B DjProcessor p1 = Dejay.getProcessorFromDB("PersistProc", "ProcesssorDB","lin:8000");

      $B"!@)8B(B/limitations

      • Java $BI8=`%/%i%9!"(Bfinal $B$,$D$$$F$$$k$b$N$O!"(B $B1s3V;2>H$GAw$l$J$$!#(BString $B$J$I$OI,$:%3%T!<$K$J$k!#(B
      • final $B$H$D$$$?%a%=%C%I$b%9%?%V$K$O4^$^$l$J$$!#(B
      • ($B%a%=%C%I8F=P$7$G$O$J$/(B) $BJQ?t$ND>@\%"%/%;%9$,$G$-$J$$!#(B
      • static $BJQ?t$O!"2>A[%W%m%;%C%5$4$H$K%3%T!<$,:n$i$l$k!#0\F0$b$G$-$J$$!#(B
      • Object $B%/%i%9$N%a%=%C%I$OA4It1s3V$KAw$i$l$k!#(B
      • Dejay $B$G$NJB9T@-$O!"K\Mh$O!"%9%l%C%I$O$J$/2>A[%W%m%;%C%5$GI=8=$9$Y$-$@$,!"(B $B%9%l%C%I$b;H$($k!#(B $BJ#?t$N%9%l%C%I$r4^$s$@2>A[%W%m%;%C%5$r0\F0$5$;$k$H(B $B$*$+$7$/$J$k!#(B
      • synchronized $B$O!"%j%b!<%H$G$O$J$/%m!<%+%k$N%9%?%V$GF/$/!#(B
      • $B%m!<%+%k!&%*%V%8%'%/%H$r%j%b!<%H%*%V%8%'%/%H$K$9$kJ}K!$,$J$$!#(B
      • DjA $B$N@8@.$G!"(BDjA $B$N%3%s%9%H%i%/%?$H(B A $B$N%3%s%9%H%i%/%?$N(B $BN>J}$,8F$P$l$k!#(B

      $B"#N}=,LdBj(B(exercise)8 $BJB9T%W%m%0%i%_%s%08@8l(B(1)/Concurrent Programming Languages(1)

      $B!zLdBj(B(801) $BHs7hDj@-(B(non-deterministic)

      CSP $B$G5-=R$5$l$?%^!<%8!&%W%m%;%9(B $B$O!"(Bthe alternative command $B$NHs7hDj@-$r$&$^$/;H$C$F$$$k!#$3$N%W%m%0%i(B $B%`$G!"%W%m%;%9(B X, Y, Z $B$,the merge process in CSP uses the non-determinismc behavior of the alternative command. In this program, consider that the processes X, Y, and Z send the following messages.
      X:: Merge ! "x1"; Merge ! "x2";
      Y:: Merge ! "y1";
      Z:: Merge ! "z1";
      
      $B$3$N;~!"(BSink $B%W%m%;%9$,
    • $BNc(B1: "x1", "y1", "z1", "x2"
    • $BNc(B2:
    • $BNc(B3:
    • $BNc(B4:

    $B!zLdBj(B(802) CSP and Ada

    CSP$B$H(BAda$B$G!"JB9T%7%9%F%`$r5-=R$9$k$?$a$K=EMW$J6&DL$N35G0$r#1$DA*$S$J$5(B $B$$!#$=$N35G0$K$D$$$F4JC1$K@bL@$7$J$5$$!#(B

    Choose one *important* common idea for describing concurrent systems in CSP and Ada. Describe this idea briefly.

    $B!zLdBj(B(803) Voyager

    XML Web $B%5!<%S%9(B(WSDL$B$,$"$k(B)$B$re$2$J$5$$!#$=$7$F!"(B $B$=$l$r4JC1$K@bL@$7$J$5$$!#(B

    Glue, which realizes XML Web services (with WSDL), and Java Remote Method Invocation (RMI) provide Remote Procedure Call (RPC). Choose an important advantage of Voyager over Glue and Java RMI. Describe this advantage briefly.

    $B!zLdBj(B(804) Voyager and Dejay

    Voyager $B$HHf3S$7$F!"(BDejay $B$N=EMW$JM%$l$F$$$kE@$r#1$D>e$2$J$5$$!#$=$7$F!"$=$l(B $B$r4JC1$K@bL@$7$J$5$$!#(B

    Choose an important advantage of Dejay over Voyager. Describe this advantage briefly.


    Last updated: 2020/06/16 16:40:11
    Yasushi Shinjo / <yas@cs.tsukuba.ac.jp>