|
CSP for Java (JCSP) 1.1-rc4 |
||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object org.jcsp.lang.Any2AnyCallChannel
public abstract class Any2AnyCallChannel
This is the super-class for any-to-any interface-specific CALL channels, safe for use by many clients and many servers.
Shortcut to the Constructor and Method Summaries.
One2OneCallChannel
for general information about CALL channels.
Documented here is information specific to this any-any version.
For example, using the same Foo interface as before, we derive:
import org.jcsp.lang.*; public class Any2AnyFooChannel extends Any2AnyCallChannel implements Foo { ... same body as One2OneFooChannel }
import org.jcsp.lang.*; class B implements CSProcess, Foo { private final ChannelAccept in; public B (final One2OneFooChannel in) { // original constructor this.in = in; } public B (final Any2AnyFooChannel in) { // additional constructor this.in = in; } ... rest as before }When wrapping the above to hide its raw method interface, don't forget to include the extra constructor(s):
import org.jcsp.lang.*; public class B2 implements CSProcess { // no Foo interface private final B b; public B2 (final One2OneFooChannel in) { // original constructor b = new B (in); } public B2 (final Any2AnyFooChannel in) { // additional constructor b = new B (in); } public void run () { b.run (); } }
accept
or not to accept a Any2AnyFooChannel - it cannot back off because
of some other event.
Parallel
.
For example, the network consisting of several clients and several servers:
where A is unchanged from its definition in One2OneCallChannel, is implemented by:Any2AnyFooChannel c = new Any2AnyFooChannel (); final A[] aClients = new A[n_aClients]; for (int i = 0; i < aClients.length; i++) { aClients[i] = new A (c); } final B2[] bServers = new B2[n_bClients]; for (int i = 0; i < bServers.length; i++) { bServers[i] = new B2 (c); } new Parallel ( new CSProcess[] { new Parallel (aClients), new Parallel (bServers) } ).run ();The clients compete with each other to find a server and the servers compete with each other to find a client. A client must not care which server it gets and vice-versa. The any-any CALL channel strictly serialises client-server transactions - only one at a time can actually take place.
It is a good idea, therefore, to restrict the duration of the CALL to as short a period as possible, so that other clients and servers are not unnecessarilly delayed. For instance, the any-any CALL can be used just to enable a client and server find one another. During the CALL, the client could give the server a private direct line (e.g. a 1-1 CALL channel) on which it promises to call back after hanging up on the shared one. The server could reply with special information (such as how long it is prepared to wait for that call back). In this way, multiple client-server transactions could proceed concurrently. An example is given below.
The college authorities have decided to charge its philosophers for all the chickens they are consuming. Unfortunately, getting the canteen to collect money from the customers would mean that its serviceTime would have to be increased from its present zero to one second. Since the canteen can only do one thing at a time, a new form of delay would be introduced into the system. Since the philosophers only think for a maximum of three seconds in between trying to eat, having them wait around (possibly for several seconds) while their colleagues make their purchases is deemed unacceptable.
The college has decided, therefore, to make some new investments. Students are to be employed to sell the chickens from the canteen. Each student is equipped with a hot-plate on which can be (indefinitely) stored one hot chicken, straight from the canteen. The student can get a chicken from the canteen (if the canteen has some available) still with the same zero serviceTime as before - the canteen has not changed. Students that have chickens compete with each other to service any customers. Servicing a customer means collecting some money and giving change, which takes one second, as well as handing over the chicken.
Hungry philosophers compete with each other to find any student who is ready for a customer. Students and philosophers find each other through a any-any CALL channel. However, if the full transaction (which includes a delay of one second) were to take place over that shared channel, the college would be no better off! The canteen-students system would still only be dealing with one customer at a time.
Therefore, the good idea mentioned at the end of the previous section is employed to enable student-philosopher transactions to proceed in parallel. The any-any shared channel is used only for a philosopher to pass over a private direct 1-1 line to a student and to exchange names (out of politeness). The bulk of all transactions takes place in parallel over unshared lines.
Here is the fixed part of the network diagram for the new college. The 1-1 channels for private communication between a philosopher (Prof) and a student (Student) are dynamically connected, continually changing and, therefore, not shown:
For this new system, the Canteen, Chef and Clock processes are unchanged. The philosophers' behaviour has changed as described above and, so, we have chosen a new name for their class - Prof. But first, we describe the new player on the block - the Student.import org.jcsp.lang.*; class Student implements CSProcess { public static interface Service { public String hello (String profId, Canteen.One2OneServiceChannel service); } public static class Any2AnyServiceChannel extends Any2AnyCallChannel implements Service { public String hello (String profId, Canteen.One2OneServiceChannel service) { join (); String n = ((Service) server).hello (profId, service); fork (); return n; } }Note that the hello CALL offers the caller's name and private 1-1 channel. These will be saved and the student's name returned when the student accepts the CALL. Notice also that that private channel instances the 1-1 Service channel exported by the Canteen. This is not surprising since the student, who will accept the CALL on that line, will be acting on behalf of the canteen - one of many proxies set up by the college to reduce the service bottleneck caused by the newly introduced charges.
Following the same pattern as for the Canteen, we next set up the constructor and the local fields for saving its parameters:
private final String id; private final ChannelAccept studentService; // provide service on this line private final Canteen.Service canteenService; // act as a client on this line private final int serviceTime; public Student (String id, Any2AnyServiceChannel studentService, Canteen.Service canteenService, int serviceTime) { this.id = id; this.studentService = studentService; this.canteenService = canteenService; this.serviceTime = serviceTime; }Now, we need to combine the exported interfaces into a single one so that the inner process can be created (anonymously) by this wrapper's run method:
private interface inner extends CSProcess, Service, Canteen.Service {}; public void run () { new inner () { private AltingChannelAccept service; // place holder for the private line private int nServed = 0; private final CSTimer tim = new CSTimer ();Impementations of the required CALL interfaces (including the one for the channel privately supplied) come next:
public String hello (String profId, Canteen.One2OneServiceChannel service) { this.service = service; System.out.println (" Student " + id + " -> Prof " + profId + " : hello ... "); return id; } public int takeChicken (String profId) { System.out.println (" Student " + id + " -> Prof +" profId + " : that'll be 1-95 please ... "); tim.sleep (serviceTime); // take the money and give any change nServed++; System.out.println (" Student " + id + " -> Prof " + profId + " : thank you - have a nice day [" + nServed + " served]"); return 1; }and the run method that conducts everything:
public void run () { System.out.println (" Student " + id + " : starting ... "); while (true) { canteenService.takeChicken (id); // make a client CALL on the canteen System.out.println (" Student " + id + " : got chicken ... ready to serve ..."); studentService.accept (this); // customer makes contact service.accept (this); // deal with customer } }Finally, don't forget to run this inner process:
}.run (); } }
import org.jcsp.lang.*; class Prof implements CSProcess { private final String id; private final Student.Service studentService; private final int thinkTime; private final int eatTime; private final boolean greedy; public Prof (String id, Student.Service studentService, int thinkTime, int eatTime, boolean greedy) { this.id = id; this.studentService = studentService; this.thinkTime = thinkTime; this.eatTime = eatTime; this.greedy = greedy; } public void run () { final CSTimer tim = new CSTimer (); final Canteen.One2OneServiceChannel service = new Canteen.One2OneServiceChannel (); // This is the private channel for // direct communication with a student int nEaten = 0; while (true) { if (! greedy) { System.out.println (" Prof " + id + " : thinking ..."); tim.sleep (thinkTime); // thinking } System.out.println (" Prof " + id + " : gotta eat ..."); String student = studentService.hello (id, service); // find a student System.out.println (" Prof " + id + " -> Student " + student + " : hi, can I have a chicken please?"); int chicken = service.takeChicken (id); // and pay up ... nEaten++; System.out.println (" Prof " + id + " : mmm ... that's good [" + nEaten + " so far]"); tim.sleep (eatTime); // eating } } }
For convenience, the college network diagram is reproduced here - naming some more of the characters. The new college seems to have attracted some good students:
Here is the code:import org.jcsp.lang.*; class NewCollege implements CSProcess { public void run () { final String[] profId = {"Bill", "Hilary", "Gennifer", "Paula", "Monica"}; final String[] studentId = {"Occam", "Babbage", "Einstein", "Turing"}; final int thinkTime = 3000; // 3 seconds final int eatTime = 100; // 100 milliseconds final int studentServiceTime = 1000; // 1 second final int canteenServiceTime = 0; // 0 seconds final int canteenSupplyTime = 3000; // 3 seconds final int maxChickens = 50; final Student.Any2AnyServiceChannel studentService = new Student.Any2AnyServiceChannel (); final Canteen.Any2OneServiceChannel canteenService = new Canteen.Any2OneServiceChannel (); final Canteen.Any2OneSupplyChannel supply = new Canteen.Any2OneSupplyChannel (); final Student[] students = new Student[studentId.length]; for (int i = 0; i < students.length; i++) { students[i] = new Student (studentId[i], studentService, canteenService, studentServiceTime); } final Prof[] profs = new Prof[profId.length]; for (int i = 0; i < profs.length; i++) { profs[i] = new Prof (profId[i], studentService, thinkTime, eatTime, i == 0); } new Parallel ( new CSProcess[] { new Clock (), new Canteen (canteenService, supply, canteenServiceTime, canteenSupplyTime, maxChickens), new Parallel (students), new Parallel (profs), new Chef ("Pierre", 4, 2000, supply), // chefId, batchSize, batchTime new Chef ("Henri", 10, 20000, supply), new Chef ("Sid", 100, 150000, supply) } ).run (); } public static void main (String argv[]) { new NewCollege ().run (); } }
One2OneCallChannel
,
Any2OneCallChannel
,
One2AnyCallChannel
,
Alternative
,
Serialized FormField Summary | |
---|---|
protected int |
selected
This may be set during the standard calling sequence to record which method was invoked by a client. |
protected CSProcess |
server
This holds a reference to a server process so that a client may make the call. |
Constructor Summary | |
---|---|
Any2AnyCallChannel()
|
Method Summary | |
---|---|
int |
accept(CSProcess server)
This is invoked by a server when it commits to accepting a CALL from a client. |
protected void |
fork()
This is invoked by a client during the standard calling sequence. |
protected void |
join()
This is invoked by a client during the standard calling sequence. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
protected CSProcess server
join
and fork
elements of the standard
calling sequence.
As shown in that sequence, it will need casting up to the relevant interface
supported by the specific CALL channel derived from this class.
protected int selected
join
and fork
elements of
that sequence. Either all the CALL
channel methods should do this or none - in the latter case, its default
value remains as zero. Its value is returned to a server as the result
the server's invocation of accept
.
Constructor Detail |
---|
public Any2AnyCallChannel()
Method Detail |
---|
public int accept(CSProcess server)
One2OneCallChannel
.
It will not complete until a CALL has been made. If the derived CALL channel has set
the selected
field in the way defined by the standard
calling sequence,
the value returned by this method will indicate which method was called.
accept
in interface ChannelAccept
server
- the server process receiving the CALL.protected void join()
accept
on this channel. In turn, that accept
will not complete until the client invokes a fork
,
after having made its CALL on the server.
protected void fork()
accept
for the client to have got this far in the sequence - see
the join
. This call unblocks that accept,
releasing the server and client to resume separate lives.
|
CSP for Java (JCSP) 1.1-rc4 |
||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |