2012-12-06 126 views
0

我很好奇,我做了什么错,因为我的void *DeleteDoneNodes(node * n)没有做任何事情,没有错误,但没有输出neighter,所以任何人都可以帮我找到我的问题的根源谢谢。删除链接的列表元素

场景:CMD线./smn m号码列表节点,n数workingThreads应该删除每个节点用node->value == 1,但它不会做任何事情......

代码:

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <unistd.h> 
#include <math.h> 
#include <semaphore.h> 

#define finishedNodes 5 
#define workersLimitNr 3 

int workingThreads = 0; 
sem_t sem; 

struct dataBlock{ 
    struct node *root; 
    int listSize; 
    int forIndex; 
}; 

struct node { // std linked list node 
    int value; 
    int worker; 
    struct node *next; 
}; 

int slots = 0; // only 3 threads are allowed to access the list 
int availableCheck(){ // check if thread can acces the list 
    if(slots < 3) 
     return 0; 
    else 
     return -1; 
} 



pthread_mutex_t mutp = PTHREAD_MUTEX_INITIALIZER; // mutex 
pthread_cond_t condvar = PTHREAD_COND_INITIALIZER; //condvar 

void *deleteDoneNodes(struct node *n){ // T H I S I S T H E F U N C 
     struct node *root = n; 
     struct node *it; 
     it = root; 
     do{ 
      if(it->value == 1){ 
       struct node *tmp; 
       printf("DELETING: %d > %d\n", it->value, it->worker); 
       root = root->next; 
       tmp = it; 
       it = it->next; 
       free(tmp); 
      } 
      else 
       it = it->next; 
    }while(it != NULL); 

    return NULL; 
} 

void * worker(void *data){ 
    struct dataBlock *inData = (struct dataBlock *) data; 
    struct node *root = inData->root; 
    int forIndex = inData ->forIndex; 
    free(data); 
    printf("* Thread id: %lu forID: %d workerNode: \n",pthread_self(),forIndex); 

    pthread_mutex_lock(&mutp); 
    if(availableCheck() < 0){ 
     printf(" ^^^ List not available yet... \n"); 
     pthread_cond_wait(&condvar, &mutp); 
    } 
    struct node *it = root; 

    printf(" _forID_ %d\n |", forIndex); 
    do{ 
     if(forIndex == it->worker){ 
      printf("valid for sqrt forIndex %d == it->worker %d\n",forIndex, it->worker); 
      if(it->value > 2){ 
       while(it->value != 1) 
       it->value = sqrt(it->value); 
       // it->value = it->value - 1; 
      } 
     } 
     it = it->next; 
    }while(it != NULL); 

    pthread_cond_signal(&condvar); // 
    pthread_mutex_unlock(&mutp); 
    return NULL; 
} 

int main(int argc, char *argv[]){ 
    if (argc != 3){ 
     printf("Programm must be called with \n NR of elements and NR of workers! \n "); 
     exit(1); 
    } 

    int i; 
    struct node *root; 
    struct node *iterator; 

//prepare list for task 
    int listSize = atoi(argv[1]); 
    int nrWorkers = atoi(argv[2]); 
    root = malloc(sizeof(struct node)); 

    root->value = rand() % 100; 
    root->worker = 0; 
    iterator = root; 

    for(i=1; i<listSize; i++){ 
     iterator->next = malloc(sizeof(struct node)); 
     iterator = iterator->next; 
     iterator->value = rand() % 100; 
     iterator->worker = i % nrWorkers; 
     printf("node #%d worker: %d value: %d\n", i, iterator->worker,iterator->value); 
    } 
    iterator->next = NULL; 
    printf("? List got populated\n"); 
// init semaphore > keeps max 3 threads working over the list 

    if(sem_init(&sem,0,3) < 0){ 
     perror("semaphore initilization"); 
     exit(0); 
    } 

// Create all threads to parse the link list 
    int ret;  
    pthread_mutex_init(&mutp,NULL); 

    pthread_t w_thread; 
    pthread_t* w_threads = malloc(nrWorkers * sizeof(w_thread)); 

    for(i=0; i < nrWorkers; i++){   
     struct dataBlock *data = malloc(sizeof(struct dataBlock)); 
     data->root = root; 
     data->listSize = listSize; 
     data->forIndex = i; 
     ret = pthread_create (&w_threads[i], NULL, worker, (void *) data); 
     if(ret) { 
      perror("Thread creation fail"); 
      exit(2);  
     } 
    } 

    deleteDoneNodes(root); 
    // printf(">>>> %d\n", root->value); 
    for (i = 0; i < nrWorkers; i++){ 
     pthread_join(w_threads[i],NULL); 
    } 
    // for (i = 0; i < nrWorkers; i++){ 
    // free(w_threads); 
    // } 

    iterator = root; 
    for (i = 0; i < listSize; i++){ 
     printf("val: %d worker: %d _ ", iterator->value, iterator->worker); 
     iterator = iterator->next; 
    } 

    free(root); 
    free(iterator); 
    return 0; 
} 

PS:它编译/ Works错误/ warningless - 用的valgrind了测试。

+1

我已经更新了我的答案中建议的代码来修复错误做到了这一点。如果你还没有遇到问题,那么你应该更新一下 – simonc

回答

1

这里有一个替代版本

void *deleteDoneNodes(struct node *n){ 
    struct node *root = n; 
    struct node *it = root; 
    struct node *prev = NULL; 
    do{ 
     if(it->value == 1){ 
      struct node *next = it->next; 
      if (prev != NULL) { 
       prev->next = next; 
      } 
      if (it == root) { 
       root = next; 
      } 
      free(it); 
      it = next; 
     } 
     else { 
      prev = it; 
      it = it->next; 
     } 
    }while(it != NULL); 

    return root; 
} 

的主要变化是:

  • 处理从该列表的中间去除的项目。前一个项目需要改变其next指针。没有这个,它会一直指向释放内存。
  • 逻辑用于更新root。这只需要,如果我们释放root
  • root沟通可能的改变发生。如果我们从列表中删除根(aka head)项目,则需要将其传递给调用者。我已经通过返回的root(可能更新)值,而不是NULL