Pthreads 《並行程序設計導論》的補充代碼

▶ 關於單鏈表的訪問,插入結點和刪除結點操做,而且將其推廣到多線程中去。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 }
相關文章
相關標籤/搜索