This is a variant of the bs.cc example that implements the same supply-chain system using a sequential style.
00001
00002
00003
00004
00005
00006
00007
00008 #include <cstdlib>
00009 #include <iostream>
00010 #include <map>
00011 #include <queue>
00012 #include <set>
00013 #include <siena/ssim.h>
00014 #include <siena/tprocess.h>
00015 #include <sstream>
00016 #include <string>
00017
00018 using namespace ssim;
00019 using namespace std;
00020
00021 int get_rand( int a, int b )
00022 {
00023 return( a + (int)(((double)rand()/(RAND_MAX+1.0))*(double)(b-a+1)) );
00024 }
00025
00026
00027
00028
00029 class Order : public Event
00030 {
00031 public:
00032 Order(const string& item, int quantity, int deliverToId)
00033 : m_item(item), m_orderId(rand()), m_quantity(quantity),
00034 m_deliverToId(deliverToId) {}
00035
00036 Order(const Order& ord)
00037 : m_item(ord.m_item), m_orderId(ord.m_orderId),
00038 m_quantity(ord.m_quantity), m_deliverToId(ord.m_deliverToId) {}
00039
00040 virtual ~Order() {}
00041
00042 const string& getItem() const
00043 {
00044 return m_item;
00045 }
00046
00047 int getOrderId() const
00048 {
00049 return m_orderId;
00050 }
00051
00052 int getQuantity() const
00053 {
00054 return m_quantity;
00055 }
00056
00057 ProcessId getDeliverToId() const
00058 {
00059 return m_deliverToId;
00060 }
00061
00062 string str() const
00063 {
00064 ostringstream oss;
00065 oss << "[Order: item=" << m_item << ",orderId="
00066 << m_orderId << ",quantity=" << m_quantity << ",deliverToId="
00067 << m_deliverToId << "]";
00068 return oss.str();
00069 }
00070
00071 private:
00072 string m_item;
00073 int m_orderId;
00074 int m_quantity;
00075 ProcessId m_deliverToId;
00076 };
00077
00078 class Delivery : public Event
00079 {
00080 public:
00081 Delivery(const string& item, int orderId, int quantity)
00082 : m_item(item), m_orderId(orderId), m_quantity(quantity) {}
00083
00084 virtual ~Delivery() {}
00085
00086 const string& getItem() const
00087 {
00088 return m_item;
00089 }
00090
00091 int getOrderId() const
00092 {
00093 return m_orderId;
00094 }
00095
00096 int getQuantity() const
00097 {
00098 return m_quantity;
00099 }
00100
00101 string str() const
00102 {
00103 ostringstream oss;
00104 oss << "[Delivery: item=" << m_item << ",orderId="
00105 << m_orderId << ",quantity=" << m_quantity << "]";
00106 return oss.str();
00107 }
00108
00109 private:
00110 string m_item;
00111 int m_orderId;
00112 int m_quantity;
00113 };
00114
00115 class Manufacturer : public TProcess
00116 {
00117 public:
00118 Manufacturer() : m_id(NULL_PROCESSID) {}
00119
00120 virtual ~Manufacturer() {}
00121
00122 virtual void main()
00123 {
00124 while( true )
00125 {
00126 const Event *e = wait_for_event();
00127 const Order *ord;
00128
00129 if ((ord = dynamic_cast<const Order *>(e)) != 0)
00130 {
00131
00132
00133
00134 int delay = m_delayMap[ord->getItem()];
00135
00136 cout << "Manufacturer(" << m_id << ") received: " << ord->str() << endl;
00137 Delivery* del = new Delivery(ord->getItem(), ord->getOrderId(),
00138 ord->getQuantity());
00139
00140 Sim::signal_event(ord->getDeliverToId(), del, delay + get_rand(0, 10));
00141 }
00142 else if (dynamic_cast<const Delivery *>(e) != 0)
00143 {
00144 cerr << "Manufacturer(" << m_id << ") received a delivery event!" << endl;
00145 }
00146 else
00147 {
00148 cerr << "Manufacturer(" << m_id << ") received unknown event" << endl;
00149 }
00150 }
00151 }
00152
00153 void addItem(const string& item, int delay)
00154 {
00155 cout << "Manufacturer(" << m_id << ") -> " << item << " takes "
00156 << delay << " days to make" << endl;
00157 m_delayMap[item] = delay;
00158 }
00159
00160 void setId(ProcessId id)
00161 {
00162 m_id = id;
00163 }
00164
00165 ProcessId getId() const
00166 {
00167 return m_id;
00168 }
00169
00170 private:
00171 ProcessId m_id;
00172 map<string,int> m_delayMap;
00173 };
00174
00175 struct item_count
00176 {
00177 int stock;
00178 int held;
00179 int ordered;
00180 int claimed;
00181 };
00182
00183 class Retailer : public TProcess
00184 {
00185 public:
00186 Retailer(ProcessId manufac_id) : m_id(NULL_PROCESSID), m_mid(manufac_id) {}
00187
00188 virtual ~Retailer() {}
00189
00190 virtual void main()
00191 {
00192 while( true )
00193 {
00194 const Delivery * d;
00195 const Order * o;
00196
00197 const Event *e = wait_for_event();
00198
00199 if ((d = dynamic_cast<const Delivery *>(e)))
00200 {
00201 handleDelivery(d);
00202 }
00203 else if ((o = dynamic_cast<const Order *>(e)))
00204 {
00205 handleOrder(o);
00206 }
00207 else
00208 {
00209 cerr << "Retailer(" << m_id << ") received unknown event." << endl;
00210 }
00211 }
00212 }
00213
00214 void addItem(const string& item, int quantity )
00215 {
00216 cout << "Retailer(" << m_id << ") -> has " << quantity << " " << item
00217 << "(s)" << endl;
00218 item_count ic;
00219 ic.stock = quantity;
00220 ic.held = 0;
00221 ic.ordered = 0;
00222 ic.claimed = 0;
00223 m_stockMap[item] = ic;
00224 }
00225
00226 ProcessId getId() const
00227 {
00228 return m_id;
00229 }
00230
00231 void setId(ProcessId id)
00232 {
00233 m_id = id;
00234 }
00235
00236 private:
00237 void handleDelivery(const Delivery* del)
00238 {
00239 item_count ic = m_stockMap[del->getItem()];
00240 int q_delivered = del->getQuantity();
00241
00242 cout << "Retailer(" << m_id << ") received: " << del->str() << endl;
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 ic.ordered -= q_delivered;
00257
00258 queue<Order*>& oqRef = m_pendingOrders[del->getItem()];
00259 queue<Order*> newQ;
00260 while(!oqRef.empty())
00261 {
00262 Order *ord = oqRef.front();
00263 oqRef.pop();
00264
00265 int q_needed = ord->getQuantity();
00266 if((ic.stock + ic.held + q_delivered) >= q_needed)
00267 {
00268
00269 Delivery *del = new Delivery(ord->getItem(), ord->getOrderId(),
00270 ord->getQuantity());
00271 Sim::signal_event(ord->getDeliverToId(), del, 1);
00272 delete ord;
00273
00274
00275 q_needed -= ic.held;
00276 if(q_needed < 0)
00277 {
00278 ic.held = -1 * q_needed;
00279 q_needed = 0;
00280 }
00281 else
00282 {
00283 ic.held = 0;
00284 }
00285
00286 if(q_needed != 0)
00287 {
00288
00289 q_needed -= ic.stock;
00290 if(q_needed < 0)
00291 {
00292 ic.stock = -1 * q_needed;
00293 q_needed = 0;
00294 }
00295 else
00296 {
00297 ic.stock = 0;
00298 }
00299
00300 if( q_needed != 0 )
00301 {
00302
00303 if(q_delivered < q_needed)
00304 {
00305 cerr << "LOGIC ERROR: q_needed=" << q_needed << endl;
00306 break;
00307 }
00308
00309 q_delivered -= q_needed;
00310 ic.claimed -= q_needed;
00311 }
00312 }
00313 }
00314 else
00315 {
00316 newQ.push(ord);
00317 }
00318 }
00319 m_pendingOrders[del->getItem()] = newQ;
00320
00321
00322 ic.stock += q_delivered;
00323
00324
00325
00326
00327
00328 m_stockMap[del->getItem()] = ic;
00329 }
00330
00331 void handleOrder(const Order* ord)
00332 {
00333
00334
00335
00336
00337
00338
00339 int q_needed = ord->getQuantity();
00340 item_count ic = m_stockMap[ord->getItem()];
00341
00342 cout << "Retailer(" << m_id << ") received: " << ord->str() << endl;
00343
00344
00345
00346
00347
00348 if(ic.stock >= q_needed)
00349 {
00350 Delivery *del = new Delivery(ord->getItem(), ord->getOrderId(), q_needed);
00351 Sim::signal_event(ord->getDeliverToId(), del, 1);
00352 ic.stock -= q_needed;
00353 }
00354 else
00355 {
00356
00357 q_needed -= ic.stock;
00358 ic.held += ic.stock;
00359 ic.stock = 0;
00360
00361
00362
00363
00364 m_pendingOrders[ord->getItem()].push(new Order(*ord));
00365 ic.claimed += q_needed;
00366
00367 if((ic.ordered - ic.claimed) < 0)
00368 {
00369 int q = ic.claimed - ic.ordered;
00370 Order *ord2 = new Order(ord->getItem(), q, m_id);
00371 Sim::signal_event(m_mid, ord2, 1);
00372 ic.ordered += q;
00373 }
00374 }
00375
00376 m_stockMap[ord->getItem()] = ic;
00377 }
00378
00379 ProcessId m_id;
00380 ProcessId m_mid;
00381 map<string,item_count> m_stockMap;
00382 map<string,queue<Order*> > m_pendingOrders;
00383 };
00384
00385 class Buyer : public TProcess
00386 {
00387 public:
00388 Buyer() : m_id(NULL_PROCESSID), m_rid(NULL_PROCESSID) {}
00389
00390 virtual ~Buyer() {}
00391
00392 void addItem(const string& item, int quantity)
00393 {
00394 m_shoppingMap[item] = quantity;
00395 }
00396
00397 virtual void main()
00398 {
00399
00400 map<string,int>::const_iterator i;
00401 for(i = m_shoppingMap.begin(); i != m_shoppingMap.end(); ++i)
00402 {
00403 Order *ord = new Order( (*i).first, (*i).second, m_id );
00404 m_delayMap[(*i).first] = get_rand( 0, 20 );
00405 Sim::signal_event(m_rid, ord, m_delayMap[(*i).first]);
00406 }
00407
00408
00409 while( true )
00410 {
00411 const Event* e = wait_for_event();
00412
00413 const Delivery* del;
00414
00415 if ((del = dynamic_cast<const Delivery*>(e)))
00416 {
00417 int sendDelay = m_delayMap[del->getItem()];
00418
00419 cout << "Buyer(" << m_id << ") order for " << del->getQuantity()
00420 << " " << del->getItem() << " took "
00421 << (Sim::clock()-sendDelay) << " days." << endl;
00422 m_shoppingMap[del->getItem()] -= del->getQuantity();
00423 }
00424 else if ((dynamic_cast<const Order *>(e)))
00425 {
00426 cerr << "Buyer(" << m_id << ") received an order event!" << endl;
00427 }
00428 else
00429 {
00430 cerr << "Buyer(" << m_id << ") received unknown event." << endl;
00431 }
00432 }
00433 }
00434
00435 ProcessId getId() const
00436 {
00437 return m_id;
00438 }
00439
00440 bool isSatisfied() const
00441 {
00442 map<string,int>::const_iterator i;
00443 bool ret = true;
00444 for(i = m_shoppingMap.begin(); i != m_shoppingMap.end(); ++i)
00445 {
00446 if( (*i).second != 0 )
00447 {
00448 cerr << "Buyer(" << m_id << ") still needs " << (*i).second << " of " << (*i).first << endl;
00449 ret = false;
00450 }
00451 }
00452 return ret;
00453 }
00454
00455 void setId( ProcessId id )
00456 {
00457 m_id = id;
00458 }
00459
00460 void setRetailerId( ProcessId id )
00461 {
00462 m_rid = id;
00463 }
00464
00465 private:
00466 ProcessId m_id;
00467 ProcessId m_rid;
00468 map<string,int> m_shoppingMap;
00469 map<string,int> m_delayMap;
00470 };
00471
00472 #define BUYER_COUNT 10
00473
00474
00475
00476
00477
00478 int main(int argc, char** argv)
00479 {
00480 srand(1);
00481
00482 set<string> items;
00483 items.insert("HardDrive");
00484 items.insert("Keyboard");
00485 items.insert("Monitor");
00486 items.insert("Mouse");
00487 items.insert("Printer");
00488 items.insert("Scanner");
00489
00490 Manufacturer m;
00491 m.setId(Sim::create_process(&m));
00492
00493 Retailer r(m.getId());
00494 r.setId(Sim::create_process(&r));
00495
00496 Buyer b[BUYER_COUNT];
00497
00498 set<string>::const_iterator i;
00499 for(i = items.begin(); i != items.end(); ++i)
00500 {
00501
00502 m.addItem((*i), get_rand(1, 30));
00503
00504
00505 r.addItem((*i), get_rand(1, 100));
00506
00507 for(int j = 0; j < BUYER_COUNT; ++j) {
00508 if(i == items.begin()) {
00509 b[j].setId(Sim::create_process(&b[j]));
00510 b[j].setRetailerId(r.getId());
00511 }
00512
00513 b[j].addItem((*i), get_rand(1, 50));
00514 }
00515 }
00516
00517 Sim::run_simulation();
00518 bool failed = false;
00519
00520
00521 for( int j = 0; j < BUYER_COUNT; ++j )
00522 {
00523 if( ! b[j].isSatisfied() )
00524 {
00525 failed = true;
00526 }
00527 }
00528 return failed;
00529 }
00530