{- Distributed Reference Cell. Based on encoding objects in Pict by Benjamin Pierce and David Turner. agentcell.pi is a distributed version of programs ref1.pi and ref2.pi that illustrate how a simple reference cell object can be implemented in Pict; agentcell.pi runs on 1-2+ machines. Specify your machines in config file, the first machine should be used to compile and execute agentcell.pi. The program creates on the first machine two reference cell objects (both are initialised with 0); after creation the objects migrate to the second machine. Then the program in turn updates the state of the first (remote) object and queries and gets back the current states of the two remote objects, which are printed locally. The values are also printed out by the objects on the remote machine as part of handling the queries. Usage: start np on remote machines, np agentcell.pi on current machine. Note: if IP address of some machine appears in config more than once (with different port numbers) then you may need to execute np on that machine with an option -p to specify which port number shall be used. -} program hosts : [Site Site Site] = ( type RefInt = [ set=/[Agent Int Sig] get=/[Agent /Int] ] def refInt [s:Site r:/RefInt] = ( new set:^[Agent Int Sig] new get:^[Agent !Int] agent refIntAg = ( new contents:^Int run contents!0 migrate to s ( set?*[a:Agent v:Int c:Sig]= contents?_ = (contents!v | c![]) | get?*[a:Agent res:!Int]= contents?v = (contents!v | printi!v | res@a!v)) ) r![ set = \[a:Agent v:Int c:Sig] = set@refIntAg![a v c] get = \[a:Agent res:!Int] = get@refIntAg![a res] ]) val s = (get_site 1) val ref1 = (refInt s) val ref2 = (refInt s) agent ag = ( (ref2.set ag 5); (prNL (int.toString (ref1.get ag))); (prNL (int.toString (ref2.get ag))); () ) ()) {-********************************************************************* * Distributed infrastructure: Simple Central Server * * Copyright (c) 2000 Pawel T. Wojciechowski * *********************************************************************-} new migrating : ^[Agent ^Site] new message : ^[#X [Agent ^Site] !X X] new deliver : ^[#X !X X Site] new ack : ^[] new done : ^^Site {Agent} = [Agent ^Site] {Site} = Site { toplevel P hosts }[Agent ^Site Agent Site] = ( val s0 = (get_site 0) val s1 = (get_site 1) val s2 = (get_site 2) agent a = (new currentloc : ^Site agent D = (print!"Server installed." | ack![] | currentloc!s0 | migrating?*[a:Agent loc:^Site]= loc?s= ack![] | message?*[#X [a:Agent loc:^Site] c:!X v:X]= loc?s= deliver![c v s]) in val SD = s0 ack?_= ( currentloc!s0 | deliver?*[#X c:!X v:X s:Site] = (currentloc!s | c!v) | (val !hosts = [s0 s1 s2] { P }[a currentloc D SD]))) ()) { agent b=P in Q }e = ( val [a loc D SD] = e loc?s= (agent B = ( new currentloc : ^Site val !b = [B currentloc] ( currentloc!s | iflocal done!currentloc then ( currentloc!s | {P}[B currentloc D SD]) else () | deliver?*[#X c:!X v:X s:Site] = (currentloc!s | c!v)) ) in done?c = (loc!s | (val !b = [B c] {Q}e))) ) { migrate to s P }e = ( val [a currentloc D SD] = e currentloc?_= ( migrating![a currentloc] | ack?_ = (migrate to s ( currentloc!s | currentloc!s | {P}e ))) ) { c@b!v }e = (val [_ _ D SD] = e val [B _] = b iflocal c!v then () else message![b c v])