Начиная с пустого списка, мне нужно, чтобы два потока работали одновременно, чтобы вставить 1 миллион случайных целых чисел каждый в один и тот же список в C - PullRequest
0 голосов
/ 24 апреля 2020

Начиная с пустого списка, мне нужно, чтобы два потока работали одновременно, чтобы вставить 1 миллион случайных целых чисел каждый в один и тот же список в C. Я пытаюсь передать пустой список создаваемой теме. Функция, похоже, не распознает ранее созданный список. Я верю, что это потому, что я ошибаюсь. Ошибка выглядит следующим образом:

ошибка: 'my_list' не объявлен (первое использование в этой функции); Вы имели в виду va_list? List_Insert (& my_list, 32);

Любой совет будет оценен.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h> 
#include <unistd.h>
#include <pthread.h>

//basic node structure
typedef struct __node_t {
    int     key;
    struct __node_t     *next;
} node_t;

//basic list structure (one used per list)
typedef struct __list_t {
    node_t      *head;
    pthread_mutex_t lock;
} list_t;


void List_Init(list_t *L) {
    L->head = NULL;
    pthread_mutex_init(&L->lock, NULL);
}

int List_Insert(list_t *L, int key) {
    pthread_mutex_lock(&L->lock);
    node_t *new = malloc(sizeof(node_t));
    if (new == NULL) {
        perror("malloc");
        pthread_mutex_unlock(&L->lock);
        return -1; //fail
    }
    new->key = key;
    new->next = L->head;
    L->head = new;
    pthread_mutex_unlock(&L->lock);
    return 0;  //success
}

int List_Lookup(list_t *L, int key) {
    pthread_mutex_lock(&L->lock);
    node_t *curr = L->head;
    while (curr) {
        if (curr->key == key) {
            pthread_mutex_unlock(&L->lock);
            return 0; //success
        }
        curr = curr->next;
    }
    pthread_mutex_unlock(&L->lock);
    return -1; //failure
}

//Ensures function executes after main
void *myThread(void *vargp) __attribute__((destructor));

int main(int argc, char *argv[]){

//Define an empty list
list_t my_list;

//Initialize the list
List_Init(&my_list);

//Create the threads
int i;
pthread_t tid;

for (i = 0; i < 2; i++)
    pthread_create(&tid, NULL, myThread, (void *)&my_list);

pthread_exit(NULL);
return 0;

}

//Function to be executed by both threads
void *myThread(void *vargp)
{
    ////FUNCTION NOT RECOGNIZING PREVIOUSLY CREATED LIST////
    printf("Inserting into list\n");
    List_Insert(&my_list, 32);

}

Ответы [ 2 ]

2 голосов
/ 24 апреля 2020

В функции потока нет my_list. После того, как вы передали my_list из main, вы можете получить к нему доступ через локальную переменную vargp (что сейчас и называется my_list)

Так что вас может заинтересовать:

void *myThread(void *vargp)
{
    printf("Inserting into list\n");
    List_Insert(vargp, 32);
    return NULL; // see man pthread_create
}

Но ... это неправильно. Потому что my_list является локальной переменной (локальной main). Поэтому, как только вы выйдете из основного потока, вы больше не сможете получить доступ к «my_list». Поэтому вам придется подождать, пока потоки завершат вызовы pthread_join() для двух потоков). Для этого вам нужно будет сохранить pthread_t идентификаторы каждого потока - в настоящее время вы перезаписываете идентификаторы потоков).

Или вам придется выделить его:

int main(int argc, char *argv[]){

    //Define an empty list
    list_t *my_list = malloc(sizeof *my_list);

    //Initialize the list
    List_Init(my_list);

    //Create the threads
    int i;
    pthread_t tid;

    for (i = 0; i < 2; i++)
        pthread_create(&tid, NULL, myThread, my_list);

    pthread_exit(NULL);
    return 0;

}

, который вы можете free() позже. Тогда вы сможете использовать myThread, как указано выше.

У вас есть другие проблемы:

  • Атрибут destructor сделает вызов myThread снова в конце. Это почти наверняка не то, что вы хотите. Вы, вероятно, хотите, чтобы поток продолжался, когда основной поток завершается. Для этого достаточно набрать pthread_exit(), как в данный момент. Поэтому просто удалите этот атрибут __attribute__((destructor)) из прототипа функции.

  • Вы должны избегать использования идентификатора с __, поскольку они являются зарезервированными именами.

  • Ваша функция потока должна возвращать указатель (как требуется pthread_create API).

1 голос
/ 24 апреля 2020

Ну, my_list - это переменная, объявленная внутри области действия main. Так что это не видно внутри функции myThread. Вы можете просто добиться этого, используя аргумент vargp:

void *myThread(void *vargp)
{
    list_t *my_list = (list_t *)vargp;
    printf("Inserting into list\n");
    List_Insert(my_list, 32);
    // Notice the missing & in the call!
}

Другая проблема заключается в том, что список размещается внутри фрейма стека функции main(). Это означает, что после возвращения main этот фрейм стека больше не доступен, и у вас будет неопределенное поведение. У вас есть 2 варианта:

  1. Либо распределите свой список по куче, используя malloc

  2. Подождите, пока все потоки внутри main функция, поэтому кадр стека main остается в живых, пока ваши потоки используют этот список.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...