心得体会
IDE自动提示补全真的特别重要,大大提高开发效率。通过IDE自动搜索库函数API。
GDB调试能力要加强。
使用前面提供的list.h来改写wordCount程序,头文件的实现相当有技巧,将使用外部list库,多线程都用宏定义到同一份代码中,这是C/C++开发的常用技巧。
这里Linux内核里面的链表实现和传统的有一些区别
word_count.h
#ifdef PINTOS_LIST
#include "list.h"
typedef struct word_count {
char* word;
int count;
struct list_elem elem;
} word_count_t;
#ifdef PTHREADS
#include <pthread.h>
typedef struct word_count_list {
struct list lst;
pthread_mutex_t lock;
} word_count_list_t;
#else /* PTHREADS */
typedef struct list word_count_list_t;
#endif /* PTHREADS */
#else /* PINTOS_LIST */
typedef struct word_count {
char* word;
int count;
struct word_count* next;
} word_count_t;
typedef word_count_t* word_count_list_t;
#endif /* PINTOS_LIST */
/* Initialize a word count list. */
void init_words(word_count_list_t* wclist);
/* Get length of a word count list. */
size_t len_words(word_count_list_t* wclist);
/* Find a word in a word_count list. */
word_count_t* find_word(word_count_list_t* wclist, char* word);
/*
* Insert word with count=1, if not already present; increment count if
* present. Takes ownership of word.
*/
word_count_t* add_word(word_count_list_t* wclist, char* word);
/* Print word counts to a file. */
void fprint_words(word_count_list_t* wclist, FILE* outfile);
/* Sort a word count list using the provided comparator function. */
void wordcount_sort(word_count_list_t* wclist, bool less(const word_count_t*, const word_count_t*));
#endif /* WORD_COUNT_H */
word_count_l.c 单线程的实现
#ifndef PINTOS_LIST
#error "PINTOS_LIST must be #define'd when compiling word_count_l.c"
#endif
#include "word_count.h"
void init_words(word_count_list_t* wclist) {
list_init(wclist);
return;
}
size_t len_words(word_count_list_t* wclist) {
return list_size(wclist);
}
word_count_t* find_word(word_count_list_t* wclist, char* word) {
struct list_elem *e;
for(e=list_begin(wclist);e!=list_end(wclist);e=list_next(e)){
word_count_t* p = list_entry(e,word_count_t, elem);
if(strcmp(p->word,word)==0){
return p;
}
}
return NULL;
}
word_count_t* add_word(word_count_list_t* wclist, char* word) {
word_count_t* p = find_word(wclist,word);
if(p!=NULL){
p->count++;
return p;
}
word_count_t* tmp = (word_count_t*)malloc(sizeof(word_count_t));
tmp->count = 1;
tmp->word = word;
list_push_back(wclist,&tmp->elem);
return tmp;
}
void fprint_words(word_count_list_t* wclist, FILE* outfile) {
struct list_elem *e;
for (e = list_begin (wclist); e != list_end(wclist);e = list_next (e)){
word_count_t *wc = list_entry(e, word_count_t, elem);
fprintf(outfile, "%8d\t%s\n", wc->count, wc->word);
}
}
static bool less_list(const struct list_elem* ewc1, const struct list_elem* ewc2, void* aux) {
/* TODO */
bool (*less)(const word_count_t *, const word_count_t *) = aux;
word_count_t *wc1 = list_entry(ewc1, word_count_t, elem);
word_count_t *wc2 = list_entry(ewc2, word_count_t, elem);
return less(wc1, wc2);
}
void wordcount_sort(word_count_list_t* wclist,
bool less(const word_count_t*, const word_count_t*)) {
list_sort(wclist, less_list, less);
}
多线程的实现很简单,在插入时保证线程完全,加锁即可。注意结构体的定义发生改变。
#ifndef PINTOS_LIST
#error "PINTOS_LIST must be #define'd when compiling word_count_lp.c"
#endif
#ifndef PTHREADS
#error "PTHREADS must be #define'd when compiling word_count_lp.c"
#endif
#include "word_count.h"
void init_words(word_count_list_t* wclist) {
list_init(&wclist->lst);
pthread_mutex_init(&wclist->lock, NULL);
}
size_t len_words(word_count_list_t* wclist) {
return list_size(&wclist->lst);
}
word_count_t* find_word(word_count_list_t* wclist, char* word) {
struct list_elem *e;
for(e=list_begin(&wclist->lst);e!=list_end(&wclist->lst);e=list_next(e)){
word_count_t* p = list_entry(e,word_count_t, elem);
if(strcmp(p->word,word)==0){
return p;
}
}
return NULL;
}
word_count_t* add_word(word_count_list_t* wclist, char* word) {
pthread_mutex_lock(&wclist->lock);
word_count_t* p = find_word(wclist,word);
if(p!=NULL){
p->count++;
}else{
p = (word_count_t*)malloc(sizeof(word_count_t));
p->count = 1;
p->word = word;
list_push_front(&wclist->lst,&p->elem);
}
pthread_mutex_unlock(&wclist->lock);
return p;
}
void fprint_words(word_count_list_t* wclist, FILE* outfile) { /* TODO */
struct list_elem *e;
for (e = list_begin(&wclist->lst);e!=list_end(&wclist->lst);e=list_next(e)){
word_count_t *wc = list_entry(e, word_count_t, elem);
fprintf(outfile, "%8d\t%s\n", wc->count, wc->word);
}
}
static bool less_list(const struct list_elem* ewc1, const struct list_elem* ewc2, void* aux) {
/* TODO */
bool (*less)(const word_count_t *, const word_count_t *) = aux;
word_count_t *wc1 = list_entry(ewc1, word_count_t, elem);
word_count_t *wc2 = list_entry(ewc2, word_count_t, elem);
return less(wc1, wc2);
}
void wordcount_sort(word_count_list_t* wclist,
bool less(const word_count_t*, const word_count_t*)) {
list_sort(&wclist->lst, less_list, less);
}
在来看一遍主函数
typedef struct thread_word_args
{
word_count_list_t* word_counts;
char* filename;
} targs_t;
void *threadfun(void *arg) {
targs_t* targs = (targs_t*)arg;
FILE *infile = fopen(targs->filename, "r");
if (infile == NULL) {
perror("fopen");
pthread_exit(NULL);
}
// pthread_mutex_lock(&targs->word_counts->lock);
count_words(targs->word_counts, infile);
// pthread_mutex_unlock(&targs->word_counts->lock);
fclose(infile);
pthread_exit(NULL);
}
/*
* main - handle command line, spawning one thread per file.
*/
int main(int argc, char* argv[]) {
/* Create the empty data structure. */
word_count_list_t word_counts;
init_words(&word_counts);
if (argc <= 1) {
/* Process stdin in a single thread. */
count_words(&word_counts, stdin);
} else {
int nthreads = argc - 1;
pthread_t threads[nthreads];
for(int i=0;i<nthreads;i++){
targs_t* targs = (targs_t *) malloc(sizeof(targs_t));
targs->filename = argv[i+1];
targs->word_counts = &word_counts;
int rc = pthread_create(&threads[i], NULL, threadfun, (void *)targs);
if(rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for(int i=0;i<nthreads;i++){
pthread_join(threads[i],NULL);
}
}
/* Output final result of all threads' work. */
wordcount_sort(&word_counts, less_count);
fprint_words(&word_counts, stdout);
pthread_exit(NULL);
return 0;
}