▶ 關於單鏈表的訪問,插入結點和刪除結點操做,而且將其推廣到多線程中去。node
● 代碼,通用的隨機數生成多線程
1 // my_rand.h 2 #ifndef _MY_RAND_H_ 3 #define _MY_RAND_H_ 4 5 unsigned my_rand(unsigned* a_p); 6 double my_drand(unsigned* a_p); 7 8 #endif 9 10 // my_rand.c 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include "my_rand.h" 14 15 #define MR_MULTIPLIER 279470273 16 #define MR_INCREMENT 0 17 #define MR_MODULUS 4294967291U 18 #define MR_DIVISOR ((double) 4294967291U) 19 20 #ifdef _MAIN_ 21 int main(void) 22 { 23 int n, i; 24 unsigned seed = 1, x; 25 double y; 26 printf("How many random numbers?\n"); 27 scanf("%d", &n); 28 29 x = my_rand(&seed); 30 for (i = 0; i < n; i++) 31 { 32 x = my_rand(&x); 33 printf("%u\n", x); 34 } 35 for (i = 0; i < n; i++) 36 { 37 y = my_drand(&x); 38 printf("%e\n", y); 39 } 40 return 0; 41 } 42 #endif 43 44 unsigned my_rand(unsigned* seed_p)// 產生 0 ~ MR_MODULUS - 1 之間的隨機整數 45 { 46 long long z = *seed_p; 47 z = (z * MR_MULTIPLIER + MR_INCREMENT) % MR_MODULUS; 48 *seed_p = z; 49 return z; 50 } 51 52 double my_drand(unsigned* seed_p)// 產生 0 ~ 1 之間的隨機雙精度浮點數 53 { 54 return (double)my_rand(seed_p) / MR_DIVISOR; 55 }
● 代碼,單線程dom
1 // linked_list.c 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 struct list_node_s 6 { 7 int data; 8 struct list_node_s* next; 9 }; 10 11 int Insert(int value, struct list_node_s** head_pp) // 插入結點 12 { 13 struct list_node_s *curr_p, *pred_p, *temp_p; 14 for (curr_p = *head_pp, pred_p = NULL; curr_p != NULL && curr_p->data < value; pred_p = curr_p, curr_p = curr_p->next);// 搜索目標位置 15 if (curr_p == NULL || curr_p->data > value) // 找到了目標位置 16 { 17 temp_p = malloc(sizeof(struct list_node_s)); 18 temp_p->data = value; 19 temp_p->next = curr_p; 20 if (pred_p == NULL) 21 *head_pp = temp_p; 22 else 23 pred_p->next = temp_p; 24 return 1; 25 } 26 printf("%d is already in the list\n", value);// 其餘狀況,目標結點已經存在(鏈表元素不容許重複) 27 return 0; 28 } 29 30 void Print(struct list_node_s* head_p) // 打印單鏈表 31 { 32 struct list_node_s *curr_p; 33 printf("list = "); 34 for (curr_p = head_p; curr_p != (struct list_node_s*) NULL; curr_p = curr_p->next) 35 printf("%d ", curr_p->data); 36 printf("\n"); 37 return; 38 } 39 40 int Member(int value, struct list_node_s* head_p) // 查找元素 value 41 { 42 struct list_node_s *curr_p; 43 44 for (curr_p = head_p; curr_p != NULL && curr_p->data < value; curr_p = curr_p->next); 45 if (curr_p == NULL || curr_p->data > value) 46 { 47 printf("%d is not in the list\n", value); 48 return 0; 49 } 50 printf("%d is in the list\n", value); 51 return 1; 52 } 53 54 int Delete(int value, struct list_node_s** head_pp) // 刪除指定結點 55 { 56 struct list_node_s *curr_p = *head_pp, *pred_p = NULL; 57 for (curr_p = *head_pp, pred_p = NULL; curr_p != NULL && curr_p->data < value; pred_p = curr_p, curr_p = curr_p->next); 58 if (curr_p != NULL && curr_p->data == value) 59 { 60 if (pred_p == NULL) 61 { 62 *head_pp = curr_p->next; 63 # ifdef DEBUG 64 printf("Freeing %d\n", value); 65 # endif 66 free(curr_p); 67 } 68 else 69 { 70 pred_p->next = curr_p->next; 71 # ifdef DEBUG 72 printf("Freeing %d\n", value); 73 # endif 74 free(curr_p); 75 } 76 return 1; 77 } 78 printf("%d is not in the list\n", value); 79 return 0; 80 } 81 82 int Is_empty(struct list_node_s* head_p) // 判斷是否爲空表 83 { 84 return head_p == NULL; 85 } 86 87 void Free_list(struct list_node_s** head_pp) // 釋放單鏈表 88 { 89 struct list_node_s *curr_p, *succ_p; 90 if (Is_empty(*head_pp)) 91 return; 92 for (curr_p = *head_pp, succ_p = curr_p->next; succ_p != NULL; free(curr_p), curr_p = succ_p, succ_p = curr_p->next) 93 { 94 # ifdef DEBUG 95 printf("Freeing %d\n", curr_p->data); 96 # endif 97 } 98 # ifdef DEBUG 99 printf("Freeing %d\n", curr_p->data); 100 # endif 101 free(curr_p); 102 *head_pp = NULL; 103 } 104 105 char Get_command(void) // 讀取下一個命令字符 106 { 107 char c; 108 printf("Please enter a command: "); 109 scanf(" %c", &c); 110 return c; 111 } 112 113 114 int Get_value(void) // 讀取下一個命令值 115 { 116 int val; 117 printf("Please enter a value: "); 118 scanf("%d", &val); 119 return val; 120 } 121 122 int main(void) 123 { 124 char command; 125 int value; 126 struct list_node_s *head_p = NULL; 127 for (command = Get_command(); command != 'q' && command != 'Q';) 128 { 129 switch (command)// 逐命令運行,忽略個操做函數的返回值 130 { 131 case 'i': 132 case 'I': 133 value = Get_value(); 134 Insert(value, &head_p); 135 break; 136 case 'p': 137 case 'P': 138 Print(head_p); 139 break; 140 case 'm': 141 case 'M': 142 value = Get_value(); 143 Member(value, head_p); 144 break; 145 case 'd': 146 case 'D': 147 value = Get_value(); 148 Delete(value, &head_p); 149 break; 150 default: 151 printf("There is no %c command\n", command); 152 printf("Please try again\n"); 153 } 154 command = Get_command(); 155 } 156 Free_list(&head_p); 157 return 0; 158 }
● 代碼,使用單互斥量函數
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <pthread.h> 4 #include "my_rand.h" 5 6 const int MAX_KEY = 100000000; 7 8 struct list_node_s 9 { 10 int data; 11 struct list_node_s* next; 12 }; 13 14 struct list_node_s *head = NULL;// 鏈表頭結點 15 int thread_count; // 線程數 16 int total_ops; // 總操做數 17 double insert_percent; // 插入操做比例 18 double search_percent; // 查找操做比例 19 double delete_percent; // 刪除操做比例 20 pthread_mutex_t mutex; // 線程操做互斥量 21 pthread_mutex_t count_mutex; // 線程操做數寫入全局和時候的互斥量 22 int member_total = 0, insert_total = 0, delete_total = 0;// 全局操做數統計 23 24 void Usage(char* prog_name) 25 { 26 fprintf(stderr, "usage: %s <thread_count>\n", prog_name); 27 exit(0); 28 } 29 30 void Get_input(int* inserts_in_main_p)// 主函數中用於輸入的函數 31 { 32 printf("How many keys should be inserted in the main thread?\n"); 33 scanf("%d", inserts_in_main_p); 34 printf("How many total ops should be executed?\n"); 35 scanf("%d", &total_ops); 36 printf("Percent of ops that should be searches? (between 0 and 1)\n"); 37 scanf("%lf", &search_percent); 38 printf("Percent of ops that should be inserts? (between 0 and 1)\n"); 39 scanf("%lf", &insert_percent); 40 delete_percent = 1.0 - (search_percent + insert_percent); 41 } 42 43 int Insert(int value)// 插入結點 44 { 45 struct list_node_s *curr, *pred, *temp; 46 for (curr = head, pred = NULL; curr != NULL && curr->data < value; pred = curr, curr = curr->next); 47 if (curr == NULL || curr->data > value) 48 { 49 temp = malloc(sizeof(struct list_node_s)); 50 temp->data = value; 51 temp->next = curr; 52 if (pred == NULL) 53 head = temp; 54 else 55 pred->next = temp; 56 return 1; 57 } 58 printf("%d is already in the list\n", value); 59 return 0; 60 } 61 62 void Print(void) 63 { 64 struct list_node_s *temp; 65 printf("list = "); 66 for (temp = head; temp != (struct list_node_s*) NULL; temp = temp->next) 67 printf("%d ", temp->data); 68 printf("\n"); 69 } 70 71 int Member(int value) 72 { 73 struct list_node_s *temp; 74 for (temp = head; temp != NULL && temp->data < value; temp = temp->next); 75 if (temp == NULL || temp->data > value) 76 { 77 # ifdef DEBUG 78 printf("%d is not in the list\n", value); 79 # endif 80 return 0; 81 } 82 # ifdef DEBUG 83 printf("%d is in the list\n", value); 84 # endif 85 return 1; 86 } 87 88 int Delete(int value) 89 { 90 struct list_node_s *curr, *pred; 91 for (curr = head, pred = NULL; curr != NULL && curr->data < value; pred = curr, curr = curr->next); 92 if (curr != NULL && curr->data == value) 93 { 94 if (pred == NULL) 95 head = curr->next; 96 else 97 pred->next = curr->next; 98 # ifdef DEBUG 99 printf("Freeing %d\n", value); 100 # endif 101 free(curr); 102 return 1; 103 } 104 return 0; 105 } 106 107 int Is_empty(void) 108 { 109 return head == NULL; 110 } 111 112 void Free_list(void) 113 { 114 struct list_node_s *current, *following; 115 if (Is_empty()) 116 return; 117 for (current = head, following = current->next; following != NULL; free(current), current = following, following = current->next) 118 { 119 # ifdef DEBUG 120 printf("Freeing %d\n", current->data); 121 # endif 122 } 123 # ifdef DEBUG 124 printf("Freeing %d\n", current->data); 125 # endif 126 free(current); 127 } 128 129 void* Thread_work(void* rank)// 調度各類鏈表工做的函數 130 { 131 int i, my_member, my_insert, my_delete; 132 unsigned seed = (long)rank + 1; 133 double which_op; 134 for (i = my_member = my_insert = my_delete = 0; i < total_ops / thread_count; i++) 135 { 136 which_op = my_drand(&seed); 137 if (which_op < search_percent)// 隨機數小於設定的搜索機率,執行搜索操做 138 { 139 pthread_mutex_lock(&mutex); 140 Member(my_rand(&seed) % MAX_KEY); 141 pthread_mutex_unlock(&mutex); 142 my_member++; 143 } 144 else if (which_op < search_percent + insert_percent)// 隨機數小於搜索和插入機率,執行插入 145 { 146 pthread_mutex_lock(&mutex); 147 Insert(my_rand(&seed) % MAX_KEY); 148 pthread_mutex_unlock(&mutex); 149 my_insert++; 150 } 151 else// 隨機數大於搜索和插入的機率,執行刪除操做 152 { 153 pthread_mutex_lock(&mutex); 154 Delete(my_rand(&seed) % MAX_KEY); 155 pthread_mutex_unlock(&mutex); 156 my_delete++; 157 } 158 } 159 pthread_mutex_lock(&count_mutex);// 將操做數加入總計數據中 160 member_total += my_member; 161 insert_total += my_insert; 162 delete_total += my_delete; 163 pthread_mutex_unlock(&count_mutex); 164 return NULL; 165 } 166 167 int main(int argc, char* argv[]) 168 { 169 int i, attempts, inserts_in_main; 170 unsigned seed = 1; 171 pthread_t *thread_handles; 172 if (argc != 2) Usage(argv[0]); 173 thread_count = strtol(argv[1], NULL, 10); 174 Get_input(&inserts_in_main); 175 176 for (i = attempts = 0; i < inserts_in_main && attempts < 2 * inserts_in_main; attempts++)// 嘗試先插入 2 * inserts_in_main 個結點 177 { 178 if (Insert(my_rand(&seed) % MAX_KEY)) 179 i++; 180 } 181 printf("Inserted %ld keys in empty list\n", i); 182 # ifdef OUTPUT 183 printf("Before starting threads, list = \n"); 184 Print(); 185 printf("\n"); 186 # endif 187 thread_handles = malloc(thread_count * sizeof(pthread_t)); 188 pthread_mutex_init(&mutex, NULL); 189 pthread_mutex_init(&count_mutex, NULL); 190 for (i = 0; i < thread_count; i++) 191 pthread_create(&thread_handles[i], NULL, Thread_work, (void*)i); 192 for (i = 0; i < thread_count; i++) 193 pthread_join(thread_handles[i], NULL); 194 printf("Total ops = %d\n", total_ops); 195 printf("member ops = %d\n", member_total); 196 printf("insert ops = %d\n", insert_total); 197 printf("delete ops = %d\n", delete_total); 198 # ifdef OUTPUT 199 printf("After threads terminate, list = \n"); 200 Print(); 201 printf("\n"); 202 # endif 203 Free_list(); 204 pthread_mutex_destroy(&mutex); 205 pthread_mutex_destroy(&count_mutex); 206 free(thread_handles); 207 return 0; 208 }
● 代碼,使用多互斥量,每一個結點一個互斥量spa
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <pthread.h> 4 #include "my_rand.h" 5 6 const int MAX_KEY = 100000000; 7 const int IN_LIST = 1; 8 const int EMPTY_LIST = -1; 9 const int END_OF_LIST = 0; 10 11 struct list_node_s// 從新定義了單鏈表結點,每一個結點增長一個互斥量 12 { 13 int data; 14 pthread_mutex_t mutex; 15 struct list_node_s* next; 16 }; 17 18 struct list_node_s* head = NULL; 19 pthread_mutex_t head_mutex; 20 int thread_count; 21 int total_ops; 22 double insert_percent; 23 double search_percent; 24 double delete_percent; 25 pthread_mutex_t count_mutex; 26 int member_total = 0, insert_total = 0, delete_total = 0; 27 28 void Usage(char* prog_name) 29 { 30 fprintf(stderr, "usage: %s <thread_count>\n", prog_name); 31 exit(0); 32 } 33 34 void Get_input(int* inserts_in_main_p) 35 { 36 printf("How many keys should be inserted in the main thread?\n"); 37 scanf("%d", inserts_in_main_p); 38 printf("How many total ops should be executed?\n"); 39 scanf("%d", &total_ops); 40 printf("Percent of ops that should be searches? (between 0 and 1)\n"); 41 scanf("%lf", &search_percent); 42 printf("Percent of ops that should be inserts? (between 0 and 1)\n"); 43 scanf("%lf", &insert_percent); 44 delete_percent = 1.0 - (search_percent + insert_percent); 45 } 46 47 void Init_ptrs(struct list_node_s** curr_pp, struct list_node_s** pred_pp)// 初始化結點指針對 *curr_pp 和 *pred_pp 48 { 49 *pred_pp = NULL; 50 pthread_mutex_lock(&head_mutex); 51 *curr_pp = head; 52 if (*curr_pp != NULL) 53 pthread_mutex_lock(&((*curr_pp)->mutex)); 54 // pthread_mutex_unlock(&head_mutex); 55 return; 56 } 57 58 int Advance_ptrs(struct list_node_s** curr_pp, struct list_node_s** pred_pp)// 將結點指針 *curr_pp 和 *pred_pp 向後移動一格 59 { 60 struct list_node_s* curr_p = *curr_pp, *pred_p = *pred_pp; 61 if (curr_p == NULL) 62 { 63 if (pred_p == NULL) 64 { 65 pthread_mutex_unlock(&head_mutex); 66 return EMPTY_LIST; 67 } 68 else 69 return END_OF_LIST; 70 } 71 if (curr_p->next != NULL) 72 pthread_mutex_lock(&(curr_p->next->mutex)); 73 if (pred_p != NULL) 74 pthread_mutex_unlock(&(pred_p->mutex)); 75 else 76 pthread_mutex_unlock(&head_mutex); 77 *pred_pp = curr_p, *curr_pp = curr_p->next; 78 return (curr_p->next == NULL) ? END_OF_LIST : IN_LIST; 79 } 80 81 int Insert(int value) 82 { 83 struct list_node_s *curr, *pred, *temp; 84 for (Init_ptrs(&curr, &pred); curr != NULL && curr->data < value; Advance_ptrs(&curr, &pred)); 85 if (curr == NULL || curr->data > value) 86 { 87 # ifdef DEBUG 88 printf("Inserting %d\n", value); 89 # endif 90 temp = malloc(sizeof(struct list_node_s)); 91 pthread_mutex_init(&(temp->mutex), NULL); 92 temp->data = value; 93 temp->next = curr; 94 if (curr != NULL) 95 pthread_mutex_unlock(&(curr->mutex)); 96 if (pred == NULL) 97 { 98 head = temp; 99 pthread_mutex_unlock(&head_mutex); 100 } 101 else 102 { 103 pred->next = temp; 104 pthread_mutex_unlock(&(pred->mutex)); 105 } 106 return 1; 107 } 108 if (curr != NULL) 109 pthread_mutex_unlock(&(curr->mutex)); 110 if (pred != NULL) 111 pthread_mutex_unlock(&(pred->mutex)); 112 else 113 pthread_mutex_unlock(&head_mutex); 114 return 0; 115 } 116 117 void Print(void)// 注意不使用互斥量 118 { 119 struct list_node_s *temp; 120 printf("list = "); 121 for (temp = head; temp != (struct list_node_s*) NULL; temp = temp->next) 122 printf("%d ", temp->data); 123 printf("\n"); 124 } 125 126 int Member(int value) 127 { 128 struct list_node_s *temp, *old_temp; 129 pthread_mutex_lock(&head_mutex); 130 if (head != NULL) 131 pthread_mutex_lock(&(head->mutex)); 132 pthread_mutex_unlock(&head_mutex); 133 for (temp = head; temp != NULL && temp->data < value;) 134 { 135 if (temp->next != NULL) 136 pthread_mutex_lock(&(temp->next->mutex)); 137 old_temp = temp; 138 temp = temp->next; 139 pthread_mutex_unlock(&(old_temp->mutex)); 140 } 141 if (temp == NULL || temp->data > value) 142 { 143 # ifdef DEBUG 144 printf("%d is not in the list\n", value); 145 # endif 146 if (temp != NULL) 147 pthread_mutex_unlock(&(temp->mutex)); 148 return 0; 149 } 150 # ifdef DEBUG 151 printf("%d is in the list\n", value); 152 # endif 153 pthread_mutex_unlock(&(temp->mutex)); 154 return 1; 155 } 156 157 int Delete(int value) 158 { 159 struct list_node_s *curr, *pred; 160 for (Init_ptrs(&curr, &pred); curr != NULL && curr->data < value; Advance_ptrs(&curr, &pred)); 161 if (curr != NULL && curr->data == value) 162 { 163 if (pred == NULL) 164 { 165 head = curr->next; 166 # ifdef DEBUG 167 printf("Freeing %d\n", value); 168 # endif 169 pthread_mutex_unlock(&head_mutex); 170 pthread_mutex_unlock(&(curr->mutex)); 171 pthread_mutex_destroy(&(curr->mutex)); 172 free(curr); 173 } 174 else 175 { 176 pred->next = curr->next; 177 pthread_mutex_unlock(&(pred->mutex)); 178 # ifdef DEBUG 179 printf("Freeing %d\n", value); 180 # endif 181 pthread_mutex_unlock(&(curr->mutex)); 182 pthread_mutex_destroy(&(curr->mutex)); 183 free(curr); 184 } 185 return 1; 186 } 187 if (pred != NULL) 188 pthread_mutex_unlock(&(pred->mutex)); 189 if (curr != NULL) 190 pthread_mutex_unlock(&(curr->mutex)); 191 if (curr == head) 192 pthread_mutex_unlock(&head_mutex); 193 return 0; 194 } 195 196 int Is_empty(void) 197 { 198 return head == NULL; 199 } 200 201 void Free_list(void) 202 { 203 struct list_node_s *current, *following; 204 if (Is_empty()) 205 return; 206 for (current = head, following = current->next; following != NULL; free(current), current = following, following = current->next) 207 { 208 # ifdef DEBUG 209 printf("Freeing %d\n", current->data); 210 # endif 211 } 212 # ifdef DEBUG 213 printf("Freeing %d\n", current->data); 214 # endif 215 free(current); 216 } 217 218 void* Thread_work(void* rank) 219 { 220 unsigned seed = (long)rank + 1; 221 int i, my_member, my_insert, my_delete; 222 double which_op; 223 for (i = my_member = my_insert = my_delete = 0; i < total_ops / thread_count; i++) 224 { 225 which_op = my_drand(&seed); 226 if (which_op < search_percent) 227 { 228 # ifdef DEBUG 229 printf("Thread %ld > Searching for %d\n", my_rank, val); 230 # endif 231 Member(my_rand(&seed) % MAX_KEY); 232 my_member++; 233 } 234 else if (which_op < search_percent + insert_percent) 235 { 236 # ifdef DEBUG 237 printf("Thread %ld > Attempting to insert %d\n", my_rank, val); 238 # endif 239 Insert(my_rand(&seed) % MAX_KEY); 240 my_insert++; 241 } 242 else 243 { 244 # ifdef DEBUG 245 printf("Thread %ld > Attempting to delete %d\n", my_rank, val); 246 # endif 247 Delete(my_rand(&seed) % MAX_KEY); 248 my_delete++; 249 } 250 } 251 pthread_mutex_lock(&count_mutex); 252 member_total += my_member; 253 insert_total += my_insert; 254 delete_total += my_delete; 255 pthread_mutex_unlock(&count_mutex); 256 return NULL; 257 } 258 259 int main(int argc, char* argv[]) 260 { 261 int i, attempts, inserts_in_main; 262 unsigned seed = 1; 263 pthread_t* thread_handles; 264 if (argc != 2) Usage(argv[0]); 265 thread_count = strtol(argv[1], NULL, 10); 266 Get_input(&inserts_in_main); 267 268 for (i = attempts = 0; i < inserts_in_main && attempts < 2 * inserts_in_main; attempts++) 269 { 270 if (Insert(my_rand(&seed) % MAX_KEY)) 271 i++; 272 } 273 printf("Inserted %ld keys in empty list\n", i); 274 # ifdef OUTPUT 275 printf("Before starting threads, list = \n"); 276 Print(); 277 printf("\n"); 278 # endif 279 thread_handles = malloc(thread_count * sizeof(pthread_t)); 280 pthread_mutex_init(&head_mutex, NULL); 281 pthread_mutex_init(&count_mutex, NULL); 282 for (i = 0; i < thread_count; i++) 283 pthread_create(&thread_handles[i], NULL, Thread_work, (void*)i); 284 for (i = 0; i < thread_count; i++) 285 pthread_join(thread_handles[i], NULL); 286 printf("Total ops = %d\n", total_ops); 287 printf("member ops = %d\n", member_total); 288 printf("insert ops = %d\n", insert_total); 289 printf("delete ops = %d\n", delete_total); 290 # ifdef OUTPUT 291 printf("After threads terminate, list = \n"); 292 Print(); 293 printf("\n"); 294 # endif 295 Free_list(); 296 pthread_mutex_destroy(&head_mutex); 297 pthread_mutex_destroy(&count_mutex); 298 free(thread_handles); 299 return 0; 300 }
● 代碼,使用讀寫鎖線程
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <pthread.h> 4 #include "my_rand.h" 5 6 const int MAX_KEY = 100000000; 7 8 struct list_node_s 9 { 10 int data; 11 struct list_node_s* next; 12 }; 13 14 struct list_node_s *head = NULL; 15 int thread_count; 16 int total_ops; 17 double insert_percent; 18 double search_percent; 19 double delete_percent; 20 pthread_rwlock_t rwlock; // 讀寫鎖 21 pthread_mutex_t count_mutex; 22 int member_total = 0, insert_total = 0, delete_total = 0; 23 24 void Usage(char* prog_name) 25 { 26 fprintf(stderr, "usage: %s <thread_count>\n", prog_name); 27 exit(0); 28 } 29 30 void Get_input(int* inserts_in_main_p) 31 { 32 printf("How many keys should be inserted in the main thread?\n"); 33 scanf("%d", inserts_in_main_p); 34 printf("How many total ops should be executed?\n"); 35 scanf("%d", &total_ops); 36 printf("Percent of ops that should be searches? (between 0 and 1)\n"); 37 scanf("%lf", &search_percent); 38 printf("Percent of ops that should be inserts? (between 0 and 1)\n"); 39 scanf("%lf", &insert_percent); 40 delete_percent = 1.0 - (search_percent + insert_percent); 41 } 42 43 int Insert(int value) 44 { 45 struct list_node_s *curr, *pred = NULL, *temp; 46 for (curr = head, pred = NULL; curr != NULL && curr->data < value; pred = curr, curr = curr->next); 47 if (curr == NULL || curr->data > value) 48 { 49 temp = malloc(sizeof(struct list_node_s)); 50 temp->data = value; 51 temp->next = curr; 52 if (pred == NULL) 53 head = temp; 54 else 55 pred->next = temp; 56 return 1; 57 } 58 return 0; 59 } 60 61 void Print(void) 62 { 63 struct list_node_s *temp; 64 printf("list = "); 65 for (temp = head; temp != (struct list_node_s*) NULL; temp = temp->next) 66 printf("%d ", temp->data); 67 printf("\n"); 68 } 69 70 int Member(int value) 71 { 72 struct list_node_s *temp; 73 for (temp = head; temp != NULL && temp->data < value; temp = temp->next); 74 if (temp == NULL || temp->data > value) 75 { 76 # ifdef DEBUG 77 printf("%d is not in the list\n", value); 78 # endif 79 return 0; 80 } 81 # ifdef DEBUG 82 printf("%d is in the list\n", value); 83 # endif 84 return 1; 85 } 86 87 int Delete(int value) 88 { 89 struct list_node_s *curr, *pred; 90 for (curr = head, pred = NULL; curr != NULL && curr->data < value; pred = curr, curr = curr->next); 91 if (curr != NULL && curr->data == value) 92 { 93 if (pred == NULL) 94 head = curr->next; 95 else 96 pred->next = curr->next; 97 # ifdef DEBUG 98 printf("Freeing %d\n", value); 99 # endif 100 free(curr); 101 return 1; 102 } 103 return 0; 104 } 105 106 int Is_empty(void) 107 { 108 return head == NULL; 109 } 110 111 void Free_list(void) 112 { 113 struct list_node_s *current, *following; 114 if (Is_empty()) 115 return; 116 for (current = head, following = current->next; following != NULL; free(current), current = following, following = current->next) 117 { 118 # ifdef DEBUG 119 printf("Freeing %d\n", current->data); 120 # endif 121 } 122 # ifdef DEBUG 123 printf("Freeing %d\n", current->data); 124 # endif 125 free(current); 126 } 127 128 void* Thread_work(void* rank) 129 { 130 int i, my_member, my_insert, my_delete; 131 unsigned seed = (long)rank + 1; 132 double which_op; 133 for (i = my_member = my_insert = my_delete = 0; i < total_ops / thread_count; i++) 134 { 135 which_op = my_drand(&seed); 136 if (which_op < search_percent) 137 { 138 pthread_rwlock_rdlock(&rwlock); 139 Member(my_rand(&seed) % MAX_KEY); 140 pthread_rwlock_unlock(&rwlock); 141 my_member++; 142 } 143 else if (which_op < search_percent + insert_percent) 144 { 145 pthread_rwlock_wrlock(&rwlock); 146 Insert(my_rand(&seed) % MAX_KEY); 147 pthread_rwlock_unlock(&rwlock); 148 my_insert++; 149 } 150 else 151 { 152 pthread_rwlock_wrlock(&rwlock); 153 Delete(my_rand(&seed) % MAX_KEY); 154 pthread_rwlock_unlock(&rwlock); 155 my_delete++; 156 } 157 } 158 pthread_mutex_lock(&count_mutex); 159 member_total += my_member; 160 insert_total += my_insert; 161 delete_total += my_delete; 162 pthread_mutex_unlock(&count_mutex); 163 return NULL; 164 } 165 166 int main(int argc, char* argv[]) 167 { 168 int i, attempts, inserts_in_main; 169 unsigned seed = 1; 170 pthread_t *thread_handles; 171 if (argc != 2) Usage(argv[0]); 172 thread_count = strtol(argv[1], NULL, 10); 173 Get_input(&inserts_in_main); 174 175 for (i = attempts = 0; i < inserts_in_main && attempts < 2 * inserts_in_main; attempts++) 176 { 177 if (Insert(my_rand(&seed) % MAX_KEY)) 178 i++; 179 } 180 printf("Inserted %ld keys in empty list\n", i); 181 # ifdef OUTPUT 182 printf("Before starting threads, list = \n"); 183 Print(); 184 printf("\n"); 185 # endif 186 thread_handles = malloc(thread_count * sizeof(pthread_t)); 187 pthread_mutex_init(&count_mutex, NULL); 188 pthread_rwlock_init(&rwlock, NULL); 189 for (i = 0; i < thread_count; i++) 190 pthread_create(&thread_handles[i], NULL, Thread_work, (void*)i); 191 for (i = 0; i < thread_count; i++) 192 pthread_join(thread_handles[i], NULL); 193 printf("Total ops = %d\n", total_ops); 194 printf("member ops = %d\n", member_total); 195 printf("insert ops = %d\n", insert_total); 196 printf("delete ops = %d\n", delete_total); 197 # ifdef OUTPUT 198 printf("After threads terminate, list = \n"); 199 Print(); 200 printf("\n"); 201 # endif 202 Free_list(); 203 pthread_rwlock_destroy(&rwlock); 204 pthread_mutex_destroy(&count_mutex); 205 free(thread_handles); 206 return 0; 207 }