home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Ebooks / Thinking in C++ V2 / C20 / BankTeller.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-25  |  3.2 KB  |  120 lines

  1. //: C20:BankTeller.cpp
  2. // From Thinking in C++, 2nd Edition
  3. // Available at http://www.BruceEckel.com
  4. // (c) Bruce Eckel 1999
  5. // Copyright notice in Copyright.txt
  6. // Using a queue and simulated multithreading
  7. // To model a bank teller system
  8. #include <iostream>
  9. #include <queue>
  10. #include <list>
  11. #include <cstdlib>
  12. #include <ctime>
  13. using namespace std;
  14.  
  15. class Customer {
  16.   int serviceTime;
  17. public:
  18.   Customer() : serviceTime(0) {}
  19.   Customer(int tm) : serviceTime(tm) {}
  20.   int getTime() { return serviceTime; }
  21.   void setTime(int newtime) {
  22.     serviceTime = newtime;
  23.   }
  24.   friend ostream& 
  25.   operator<<(ostream& os, const Customer& c) {
  26.     return os << '[' << c.serviceTime << ']';
  27.   }
  28. };
  29.  
  30. class Teller {
  31.   queue<Customer>& customers;
  32.   Customer current;
  33.   static const int slice = 5;
  34.   int ttime; // Time left in slice
  35.   bool busy; // Is teller serving a customer?
  36. public:
  37.   Teller(queue<Customer>& cq) 
  38.     : customers(cq), ttime(0), busy(false) {}
  39.   Teller& operator=(const Teller& rv) {
  40.     customers = rv.customers;
  41.     current = rv.current;
  42.     ttime = rv.ttime;
  43.     busy = rv.busy;
  44.     return *this;
  45.   }
  46.   bool isBusy() { return busy; }
  47.   void run(bool recursion = false) {
  48.     if(!recursion)
  49.       ttime = slice;
  50.     int servtime = current.getTime();
  51.     if(servtime > ttime) {
  52.       servtime -= ttime;
  53.       current.setTime(servtime);
  54.       busy = true; // Still working on current
  55.       return;
  56.     }
  57.     if(servtime < ttime) {
  58.       ttime -= servtime;
  59.       if(!customers.empty()) {
  60.         current = customers.front();
  61.         customers.pop(); // Remove it
  62.         busy = true;
  63.         run(true); // Recurse
  64.       }
  65.       return;
  66.     }
  67.     if(servtime == ttime) {
  68.       // Done with current, set to empty:
  69.       current = Customer(0);
  70.       busy = false;
  71.       return; // No more time in this slice
  72.     }
  73.   }
  74. };
  75.  
  76. // Inherit to access protected implementation:
  77. class CustomerQ : public queue<Customer> {
  78. public:
  79.   friend ostream& 
  80.   operator<<(ostream& os, const CustomerQ& cd) {
  81.     copy(cd.c.begin(), cd.c.end(), 
  82.       ostream_iterator<Customer>(os, ""));
  83.     return os;
  84.   }
  85. };
  86.  
  87. int main() {
  88.   CustomerQ customers;
  89.   list<Teller> tellers;
  90.   typedef list<Teller>::iterator TellIt;
  91.   tellers.push_back(Teller(customers));
  92.   srand(time(0)); // Seed random number generator
  93.   while(true) {
  94.     // Add a random number of customers to the
  95.     // queue, with random service times:
  96.     for(int i = 0; i < rand() % 5; i++)
  97.       customers.push(Customer(rand() % 15 + 1));
  98.     cout << '{' << tellers.size() << '}' 
  99.       << customers << endl;
  100.     // Have the tellers service the queue:
  101.     for(TellIt i = tellers.begin(); 
  102.       i != tellers.end(); i++)
  103.       (*i).run();
  104.     cout << '{' << tellers.size() << '}' 
  105.       << customers << endl;
  106.     // If line is too long, add another teller:
  107.     if(customers.size() / tellers.size() > 2)
  108.       tellers.push_back(Teller(customers));
  109.     // If line is short enough, remove a teller:
  110.     if(tellers.size() > 1 && 
  111.       customers.size() / tellers.size() < 2)
  112.       for(TellIt i = tellers.begin();
  113.         i != tellers.end(); i++)
  114.         if(!(*i).isBusy()) {
  115.           tellers.erase(i);
  116.           break; // Out of for loop
  117.         }
  118.   }
  119. } ///:~
  120.