Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

239 lines (169 sloc) 5.95 kb
import edu.ucdavis.jr.*;
import java.util.*;
import java.util.ArrayList;
public class Door {
private ArrayList<Person> entrants;
private int landlordCalls;
private cap void() returnOkCap = null;
public op int add(Person p);
public op boolean isClosed();
public op List<Person> lock(cap void() returnOkCap);
public cap List<Person>(cap void() returnOkCap) lastCall = lock;
public op void leave(Person p);
public Door() {
entrants = new ArrayList<Person>();
landlordCalls = 0;
Global.door = this;
}
private process doorProcess {
startLoop();
System.out.println("Door process exits ...");
}
// I added this as a seperate method to be able to override stupid warnings
@SuppressWarnings("unchecked")
private void startLoop()
{
while(true)
{
inni ArrayList<Person> lock(cap void() returnOkCap)
{
landlordCalls++;
this.returnOkCap = returnOkCap;
return new ArrayList<Person>(entrants); // This adds stupid warning
}
[] int add(Person p)
{
asserts(!entrants.contains(p), "Person " + p + " has already entered door");
if(landlordCalls < 2)
{
addPersonToList(p);
}
return landlordCalls;
}
[] void leave(Person p)
{
removePersonFromList(p);
if(entrants.size() <= 2 && returnOkCap != null)
{
// Ok, only landlord (or ll+assistant) should be left, lets notify him
send returnOkCap();
}
if(entrants.size() == 0)
{
// Ok, now even landlord left, lets exit gracfully
break;
}
}
[] boolean isClosed()
{
return landlordCalls >= 2;
}
}
}
@SuppressWarnings("unchecked")
private void addPersonToList(Person p)
{
entrants.add(p); // This darn command adds stupid warning
}
@SuppressWarnings("unchecked")
private void removePersonFromList(Person p)
{
entrants.remove(p); // This darn command adds stupid warning
}
/***************************************************
TESTING CODE BELOW
***************************************************/
public static void main(String[] args) {
allDoorTests();
}
public static void allDoorTests()
{
testOnePersonEnters();
testOnePersonLeaving();
testDoor();
System.out.println("Door tests passed.");
}
// This test is starting other threads
public static void testOnePersonEnters()
{
Door d = new Door();
asserts(d.entrants.size() == 0, "Door should start empty");
TestPerson p = new TestPerson();
JR.nap(100);
asserts(d.entrants.get(0) == p, "Person p should be in list");
asserts(d.entrants.size() == 1, "Should only be 1 person in list");
p.setGoHome();
JR.nap(100);
}
// This test is starting other threads
public static void testOnePersonLeaving()
{
Door d = new Door();
TestPerson p = new TestPerson();
JR.nap(100);
p.setGoHome();
JR.nap(100);
asserts(d.entrants.size() == 0, "Everyone should have exited.");
}
// This test runs in a two threads (test+Doorprocess) and only emulates a person
// What is good with this test is that it doesn't depend on Person
// This test tests most behavior
public static void testDoor()
{
Door d = new Door();
TestPerson p1 = new TestPerson(); //fakeperson
JR.nap(100);
asserts(d.entrants.size() == 1, "Should only be 1 person in list");
TestPerson p2 = new TestPerson(); // another entrant
JR.nap(100);
asserts(d.entrants.size() == 2, "Two should 've entered");
asserts(d.entrants.contains(p1), "p1 should be in list");
asserts(d.entrants.contains(p2), "p2 should be in list");
TestPerson landlord = new TestPerson(); // this emulates Landlord (auto-enters)
JR.nap(100);
op void returnCap(); // The landlords replyChannel
List<Person> list = d.lastCall(returnCap);
list = d.lock(returnCap); // Now we must close
asserts(list != d.entrants, "Should not be reference to entrants!");
asserts(list.equals(d.entrants), "Should however be equal to entrants!");
TestPerson p3 = new TestPerson(); // this one will emulate door-rejected customer
JR.nap(100);
asserts(d.entrants.size() == 3, "Nobody should've entered yet since it was locked (2persons + landlord is in)");
// Now let p1 leave
p1.setGoHome();
JR.nap(100);
asserts(d.entrants.size() == 2, "only 1 + landlord should be left");
asserts(d.entrants.contains(p2), "p2 should be left");
JR.nap(100);
// make sure we have got reply yet
inni void returnCap()
{ /* landing here is good :) */ }
[] else {
asserts(false, "The closing signal is not sent even though assistant left!");
}
// Now let p2 leave
p2.setGoHome();
JR.nap(100);
asserts(d.entrants.size() == 1, "Only landlord should be in!");
asserts(d.entrants.contains(landlord), "Only landlord should be in");
JR.nap(100);
// make sure we HAVE got reply now
inni void returnCap()
{ /* landing here is good :) */ }
[] else {
asserts(false, "The closing signal was not sent!");
}
landlord.setGoHome();
JR.nap(100);
asserts(d.entrants.isEmpty(), "Everyone should've leaved");
JR.nap(100);
}
public static void asserts(boolean b, String s)
{
if(!b)
{
System.out.println("DoorAssert failed: " + s);
System.exit(1);
}
}
}
Jump to Line
Something went wrong with that request. Please try again.