contributed <shelly4132
>
$ lscpu
$ make
$ ./sort 4 8
input unsorted data line-by-line
5
2
11
65
1
9
30
0
sorted results:
[0] [1] [2] [5] [9] [11] [30] [65]
後面兩個參數分別填上thread的數量和總共要排序多少數字,輸入完後再將要排序的數字一行一行打上去,最後就會顯示排序好的數列。
如果不想自己手動打的話也可以利用$RANDOM
環境變數取得介於 0~32767 之間的亂數。
$ (for i in {1..8}; do echo $RANDOM; done) | ./sort 4 8
input unsorted data line-by-line
sorted results:
[1623] [2036] [3472] [3809] [11126] [23029] [28806] [30389]
typedef struct _task {
void (*func)(void *);
void *arg;
struct _task *next, *last;
} task_t;
typedef struct {
task_t *head, *tail;
pthread_mutex_t mutex;
pthread_cond_t cond;
uint32_t size;
} tqueue_t;
typedef struct {
pthread_t *threads;
uint32_t count;
tqueue_t *queue;
} tpool_t;
指派第一個task並將之放進job queue裡,the_list
是前面建好的使用者輸入數列的linked list,而cut_func()
就是用來切割數列的。
task_t *_task = (task_t *) malloc(sizeof(task_t));
_task->func = cut_func;
_task->arg = the_list;
tqueue_push(pool->queue, _task);
intptr_t:
可pointer轉換成integer型態,能做位元運算與加減法等等。但如果要做位元運算的話無號的uintptr_t
會是比較好的選擇。
merge_list()
傳入兩個list,然後去比較2個list最小的那個再一一挑出,放到新的list裡面,直到其中一個list的數被挑完,還有數字的list就接到已排序好的list後面。
merge_sort()
如果傳入的list size小於2直接回傳該list,否則就將他從中間分成2個list之後丟進merge_list()
做排序並回傳排序好的list。
merge
裡面去判斷現在的list總共串了幾個,如果小於輸入的資料數,就繼續做排序串起來,不然就設置終止task然後印出排序好的list。
發現cut_func()跟merge_sort()都是再做切割list,而cut_func裡面判斷cut_count是否小於max_cut其實沒有必要,所以把cut_count等相關變數刪掉,也把merge_sort()刪掉,留下cut_func()就好。
由一個boss thread去接收input並分派task給其他worker thread。
將我們要做的事寫成task,放進job queue裡,空閒的thread會從queue裡拿task出來做。
去queue裡面提取task。
static void *task_run(void *data)
{
(void) data;
while (1) {
task_t *_task = tqueue_pop(pool->queue);
if (_task) {
if (!_task->func) {
tqueue_push(pool->queue, _task);
break;
} else {
_task->func(_task->arg);
free(_task);
}
}
}
pthread_exit(NULL);
}
新增一個test_input.c
會產生亂數於test_input.txt
裡,原本的程式去讀取他後去做merge sort將結果輸出於output.txt
中,最後再將output.txt
與由output.txt
sort完後的sorted.txt
去做比較,如果結果都一樣就輸出「Verified OK」。
typedef char val_t[16];
使用uniq words.txt | sort -R > words_input.txt
讓原本排序好的words.txt順序打亂,變成merge sort新的輸入。
在merge_list()
裡的比大小改為用strcmp(a->head->data, b->head->data)
的回傳值去做判斷,若前者較大回傳值大於0,等於回傳0,否則回傳負值。
while (fgets(answer, sizeof(answer), fp1) != NULL) {
fgets(output, sizeof(output), fp2);
if (strcmp(answer, output) != 0) {
printf("Wrong Answer!\n");
return 0;
}
}
printf("Verified OK\n");