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: