Untitled

 avatar
unknown
plain_text
5 months ago
2.5 kB
7
Indexable
#include "q2tallyVotes.h"
#include "q2print.h"

void TallyVotes::wait() {
	bench.wait();							// wait until signalled
	while ( rand() % 2 == 0 ) {				// multiple bargers allowed
		try {
			_Accept( vote || done ) {		// accept barging callers
			} _Else {						// do not wait if no callers
			} // _Accept
		} catch( uMutexFailure::RendezvousFailure & ) {}
	} // while
}

void TallyVotes::signalAll() {				// also useful
	while ( ! bench.empty() ) bench.signal(); // drain the condition
}

TallyVotes::Tour TallyVotes::vote ( unsigned int id, Ballot ballot ) {
	if (voters < group) {	// if in quorum failure state, immediately throw
		_Throw Failed();
	}

    int currentTicket = ticket;
    ticket++;
    while(true) {
        if (votersFinalized && currentTicket > currentTicketLimit)  {
            wait();
        } else {
            break;
        }
    }

    VOTER_ENTER( group );

	currentlyVoted++;

    numPictures += ballot.picture;	// update tally counts
	numStatues += ballot.statue;
	numGifts += ballot.giftshop;

	printer.print(id, Voter::States::Vote, ballot);

	if (currentlyVoted == 0) {
		groupNumber++;
	}
	
	Tour t;
	t.groupno = groupNumber;
	if (currentlyVoted == group) {	// everyone in the group has voted
		// calculate the winner
		if (numGifts >= numPictures && numGifts >= numStatues) {
			destination = TallyVotes::TourKind::GiftShop;
		} else if (numPictures >= numStatues) {
			destination = TallyVotes::TourKind::Picture;
		} else {
			destination = TallyVotes::TourKind::Statue;
		}

		numGifts = 0;	// reset values to 0 as we are done with the current tour
		numPictures = 0;
		numStatues = 0;

        currentTicketLimit = currentTicket;
        votersFinalized  = true;

        signalAll();
		
		t.tourkind = destination;
		printer.print(id, Voter::States::Complete, t);
	} else {
		printer.print(id, Voter::States::Block, currentlyVoted);

		wait();

        if (voters < group && !votersFinalized) {
            _Throw Failed();
        }

		printer.print( id, Voter::States::Unblock, currentlyVoted - 1);
	}
	t.tourkind = destination;
	currentlyVoted--;

    if (currentlyVoted == 0) {
        votersFinalized = false;
        signalAll();
    }

    VOTER_LEAVE( group );
	return Tour{destination, groupNumber};
}

void TallyVotes::done(
	#if defined( TASK )
	unsigned int id
	#endif
) {
	voters--;
    if (voters < group) {
        signalAll();
    }
}
Editor is loading...
Leave a Comment