Long Answers CS343
W23
External scheduling:
L1:
bool clientWaiting = false;
bool taxiWaiting = false;
L2: getTaxi
clientWaiting = true;
xclient = x;
yclient = y;
clientId = id;
_When(!taxiWaiting) _Accept(getClient) {}
clientWaiting = false;
L3: getClient
taxiWaiting = true;
taxiId = id;
_When(!clientWaiting) _Accept(getTaxi) {}
taxiWaiting = false;
x = xclient;
y = yclient;
Internal scheduling:
L1:
uCondition waitingTaxis, waitingClients;
L2: getTaxi
if (!waitingTaxis.empty()) { // A taxi is available
xclient = x;
yclient = y;
clientId = id; // Store client details
taxiId = waitingTaxis.front(); // Get the taxi from the front of the queue
waitingTaxis.signalBlock(); // Unblock the waiting taxi
} else { // No taxis are available
waitingClients.wait(id); // Block the client and wait for a taxi
xclient = x;
yclient = y;
clientId = id; // Store client details once unblocked
}
L3: getClient
if (!waitingClients.empty()) { // A client available
taxiId = id; // Store the taxi ID
waitingClients.signalBlock(); // Unblock the waiting client
} else {
waitingTaxis.wait(id); // Block the taxi and wait for a client
}
AUTOMATIC_SIGNAL: i give up
L1:
AUTOMATIC_SIGNAL;
int waitingTaxis = 0; waitingClients = 0;
L2: getTaxi
waitingCl
Administrator:
void MapleLeafTaxi::main(){
Taxi* taxiT[NoOfTaxi]; // here it's 5
// allocate taxis
for(unsigned int i = 0; i < NoOfTaxi; i++) {
taxiT[i] = new Taxi(*this, i); // assign id
}
for(;;) {
_Accept(close) {
break;
} or _Accept(getClient or getTaxi) {
LocnClient *n = client.front();
clients.pop_front();
// Store location of client
xclient = n->x;
yclient = n->y;
// Find nearest taxi
list<LocnTaxi*>::iterator closest = nearestTaxi(xlient, yclient, taxis);
// Store the future taxi
n->ftaxi.delivery(closest->id);
delete n;
// unblock assigned taxi
closest->idle.signalBlock();
taxis.erase(closet);
}
} // for
osacquire( cout ) << "Closed for the day." << endl;
// outstanding taxis blocked
while(clients.size() != 0) {
LocnClient* c = clients.front();
clients.pop_front();
c->ftaxi.exception(new Closed); // Notify clients that no taxis are available
delete client;
}
closed = true; // // Mark the dispatcher as closed
// wait for remaining taxis
for(int i = 0; i < NoOfTaxi; i++) {
if(taxis.empty()) _Accept(getClient); // wait for taxi
taxis.front()->idle.signalBlock(); //??
taxis.pop_front(); // unblock with closed
}
for(int i = 0; i < NoOfTaxi; i++) delete taxiT[i];
}
F18
External scheduling:
_Monitor Semaphore {
unsigned int cnt;
public:
Semaphore(unsigned int cnt) : cnt(cnt) {}
void P(){
if(cnt == 0) {
for(;;) {
_Accept(V) {
} _Accept(try P()){
}
} // for
} // if
cnt--;
}
bool tryP(){
if(cnt == 0) {
return false
}
cnt--; // why? didn't have it initially
return true;
}
void P(Semaphore s) {
s.V();
P();
}
void V() {
cnt++;
}
}
counter of a semaphore only goes from 0 to 1.
P(Semaphore s)
This sequence can occur in scenarios where:
- A higher-level resource allocation must be made available (
s.V()
). - Immediately after, the current process or thread attempts to acquire the resource (
P()
). This could be because other tasks may also compete for the resource, and the code ensures the resource is claimed for use immediately after signalling availability.
Internal scheduling:
_Monitor Semaphore {
unsigned int cnt;
uCondition bench;
public:
Semaphore(unsigned int cnt) : cnt(cnt) {}
void P(){
if(cnt == 0) bench.wait();
cnt--;
}
bool tryP(){
if(cnt == 0) return false;
cnt--;
return true;
}
void P(Semaphore s) {
s.signal();
P();
}
void V() {
cnt--;
bench.signal();
}
}
F19
External scheduling:
L1: // Don't need any variables
L2:
if(voters < group) _Throw Quorum();
L3:
try {
for(;;) {
_Accept(done) {
if(voters < group) break;
} or _Accept(vote){
}
} // for
} catch (uMutexFailure::RendezvousFailure &){
} // try
L5:
if(voters < group) _Throw Quorum();
Internal scheduling:
L1:
uCondition bench;
L2:
if(voters < group) _Throw Quorum();
L3:
bench.wait();
bench.signal();
if(voters < group) _Throw Quorum();
L4:
bench.signal();
L6:
if(voters < group) bench.signal();
Administrator:
void flush(bool kind) {
for(int i = 0; i < votes.size(); i++) {
votes[i]->(kind ? new Quorum : new Closed);
} // for
votes.clear();
}
void main(){
for(;;){
_Accept(~TallyVotes){ // shutdown
break;
} or _Accept(done) { // voter leaves
voters -= 1;
if(voters < group && voters.size()) { // failure?
flush(true); // Quorum failure
}
} or _Accept(vote) { // voter
} or _Accept(tour) { //guide
if(!wguides.empty() && voters.size() > group) {
for(int i = 0; i < group; i++){ //compute rank
add(voters->[i]->ballot);
} // for
gtour = tally(); // computer vote
for(int i = 0; i < group; i++) { // put vote in futures
votes[i]->ftour.delivery(gtour);
delete votes[i];
} // for
votes.erase(votes.begin(), votes.begin()+group) // shorten
wguides.signalBlock(); // unblock guide
reset(); // reset vote counters
} // if
} // Accept
} // for
// Shut down and tell the tourists/guides to go home
closed = true;
for(int i = 0; i < guides; i++){
if(wguides.empty()) _Accept(tour);
} // for
flush(false); // CLosed failure
}
External scheduling:
unsigned int winner;
bool shutdownStarted = false;
TallyBets::Payout TallyBets::placeBet(BetSlip slip) {
if(shutdownStarted) _Throw Leave();
try {
_Accept(done) {
} or _Accept(race) {
} or _Accept(placeBet) {
}
} catch(uMutexFailure::RendezvousFailure & ) {}
if(shutdownStarted) _Throw Leave();
return tally(slip);
} // TallyBets::placeBet
void TallyBets::race(unsigned int winner) {
TallyBets::winner = winner;
} // TallyBets::race
void done() {
shutdownStarted = true;
} // TallyBets::done
Internal scheduling
uCondition bench;
TallyBets::Payout TallyBets::placeBet(BetSlip slip) {
if(shutdownStarted) _Throw Leave();
bench.wait();
bench.signal();
if(shutdownStarted) _Throw Leave();
return tally(slip);
} // TallyBets::placeBet
void TallyBets::race(unisgned int winner) {
TallyBets::winner = winner;
bench.signal();
} // TallyBets::race
void done(){
shutdownStarted = true;
} // TallyBets::done
Automatic signal:
AUTOMATIC_SIGNAL;
unsigned int numBets = 0;
TallyBets::Payout TallyBets::placeBet(BetSlip slip) {
if(shutdownStarted) _Throw Leave();
numBets += 1;
WAITUNTIL(numBets == 0, , );
if(shutdownStarted) _Throw Leave();
EXIT();
return tally(slip);
} // TallyBets::placeBet
void TallyBets::race(unsigned int winner) {
TallyBets::winner = winner;
numBets = 0;
EXIT();
} // TallyBets::race
void done() {
shutdownStarted = true;
} // TallyBets::done
Administrator:
struct Work {
BetSlip slip;
FPayout fpayout;
Work(BetSlip slip): slip(slip) {}
};
FPayout placeBet(BetSlip slip);
Work* node;
list<Work*> students; // students waiting for race results
unsigned int numStuds;
TallyBets(unsigned int numStuds): numStuds(numStuds) {}
TallyBets::FPayout TallyBets::placeBet(BetSlip slip) {
node = new Work(slip);
return node->fpayout; // why?
} // TallyBets::placeBet
// same as monitor
void TallyBets::race(unsigned int winner) {}
// same as monitor
void TallyBets::done(){}
void TallyBets::main() {
for(;;) {
_Accept(done) {
break;
} or _Accept(race) {
while(!students.empty()) {
Work* n = students.front();
students.pop_front();
n->fpayout.delivery(tally(n->slip));
delete n;
} // while
} or _Accept(placeBet) {
students.push_back(node); // store future
} // _Accept
} // for
// Students not waiting on futures.
unsigned int rem - numStuds - 1 - students.size();
for(unsigned int b = 0; b < rem; b+=1) {
_Accept(placeBet) {
students.push_back(node);
Work* n = students.front();
students.pop_front();
n->fpayout.delivery(new Leave());
delete n;
} or _Accept(done) {}
} // for
// Students waiting on futures
while(!students.empty()) {
Work* n = students.front();
students.pop_front();
n->fpayout.delivery(new Leave());
delete n;
} // while
} // TallyBets::main
F15
Write a counting semaphore using μC++ monitors that implements the semaphore lock
External scheduling:
void P() {
if(counter == 0) {
_Accept(V) {}
}
counter--;
}
void V() {
counter++;
}
Internal scheduling:
uCondition bench;
void P() {
if(counter == 0) {
bench.wait();
}
counter--;
}
void V() {
bench.signal();
counter++;
}
Internal scheduling with barging, using only routines wait() and signalAll():
int tickets = 0;
int servings = 0;
void P() {
unsigned int myticket = tickets; // select ticket
ticket++; // advance ticket for next barger
while(myticket != serving) wait(); // my turn to go?
}
void V() {
serving++;
signalAll();
}
Automatic signal:
AUTOMATIC_SIGNAL;
void P() {
WAITUNTIL(counter != 0, , )
counter--;
}
void V() {
counter++;
EXIT()
}
Administrator: