1. Concurrency APIs used in Lab 3 1 void smutex_init(smutex_t *mutex); 2 void smutex_destroy(smutex_t *mutex); 3 4 void smutex_lock(smutex_t *mutex); 5 void smutex_unlock(smutex_t *mutex); 6 7 8 void scond_init(scond_t *cond); 9 void scond_destroy(scond_t *cond); 10 11 void scond_signal(scond_t *cond, smutex_t *mutex); 12 void scond_broadcast(scond_t *cond, smutex_t *mutex); 13 void scond_wait(scond_t *cond, smutex_t *mutex); 2. the tobacco problem from homework 3 1 class Table { 2 public: 3 void matchSmokerUseTable(); 4 void paperSmokerUseTable(); 5 void tobaccoSmokerUseTable(); 6 void agentUseTable(); 7 Table(); 8 int getPaper(); 9 int getTobacco(); 10 int getMatch(); 11 ~Table(); 12 private: 13 scond_t tableEmptyCond; // contract: when table is empty, signal this 14 scond_t tableFullCond; // when table is full, signal this 15 smutex_t tableMutex; 16 int paper, tobacco, match; // shared state, encapsulated 17 // table is small, so can at most have two items at once 18 bool tableIsFull(); 19 bool tableIsEmpty(); 20 }; 21 22 Table:: 23 Table() { 24 paper = 0; 25 tobacco = 0; 26 match = 0; 27 scond_init(&tableFullCond); 28 scond_init(&tableEmptyCond); 29 smutex_init(&tableMutex); 30 } 31 32 Table:: 33 ~Table() { 34 scond_destroy(&tableEmptyCond); 35 scond_destroy(&tableFullCond); 36 smutex_destroy(&tableMutex); 37 } 38 39 // warm up example 40 int Table:: 41 getPaper() { 42 smutex_lock(&tableMutex); 43 int r = paper; 44 smutex_unlock(&tableMutex); 45 return r; 46 } 47 // get tobacco and get match is similar 48 49 50 // private method, why we don't need mutex here? 51 bool Table:: 52 tableIsFull() { 53 return paper + tobacco + match >= 2; 54 } 55 56 bool Table:: 57 tableIsEmpty() { 58 return !tableIsFull(); 59 } 60 61 void Table:: 62 agentUseTable() { 63 smutex_lock(&tableMutex); 64 while (tableIsFull()) { 65 scond_wait(&tableEmptyCond, &tableMutex); 66 } 67 chooseIngredients(&paper, &tobacco, &match); 68 // why broadcast intead of signal? 69 scond_broadcast(&tableFullCond, &tableMutex); 70 smutex_unlock(&tableMutex); 71 } 72 73 void Table:: 74 paperSmokerUseTable() { 75 smutex_lock(&tableMutex); 76 while(tableIsEmpty() || (match < 1 || tobacco < 1)) { 77 scond_wait(&tableFullCond, &tableMutex); 78 } 79 match--; 80 tobacco--; 81 scond_signal(&tableEmptyCond, &tableMutex); 82 smutex_unlock(&tableMutex); 83 } 84 85 Table table; // shared memory encapsulated in a Table instance 86 void agent() { // Agent thread function, smoker thread is similar 87 while (1) { 88 table.agentUseTable(); 88 } 89 } 90