Страницы

Поиск по вопросам

пятница, 7 февраля 2020 г.

Передача двух массивов в поток

#c #многопоточность


Имеется 2 структуры (2 динамических массива), в каждой свой набор данных. Появилась
потребность перенести одну из функций в поток с помощью pthread_create (функцию change).

Не могу понять, как можно передать ссылки на эти 2 структуры в данную функцию (в
потоке), чтобы в ней я смог провести какие-нибудь операции у данных структур и с этими
изменениями я мог дальше работать в основной программе?

Спасибо.

Пример программы.

#include 
#include 
#include 
#include 
#include 
#include 

struct strc {
 char str[60];
 int uid;
 struct strc *prev;
};

struct param {
 struct stack *elma;
 struct stack *elmb;
};

struct stack *add(struct stack **base, char *line,int uid) {
 struct stack *element=(struct stack*)malloc(sizeof(struct stack));
 element->prev=*base;
 strcpy(element->data,line);
 element->uid=uid;
 return element;
}

int search(struct stack *base,char *str) {
 while (base!=NULL) {if (strcmp(base->data,str)==0) return base->uid; base=base->prev;}
 return 0;
}

void * change(void *arg) {
 struct param *data=arg;

 *data.elma=add(data.elma,"chips",5); 
 *data.elmb=add(data.elmb,"volvo",2); 
}

int main() {
 int uid;
 pthread_t thread;
 struct strc *elma=NULL;
 struct strc *elmb=NULL;
 struct param *arg;

 arg->elma=elma;
 arg->elmb=elmb;

 if (pthread_create(&thread, NULL, change, &arg) != 0) {return -1;}

 uid=search(elma,"chips");
 printf("%i",uid);
 uid=search(elmb,"volvo");
 printf("%i",uid);
}

    


Ответы

Ответ 1



Поправил Ваш пример до работоспособного состояния. #include #include #include #include #include #include #include struct stack { char data[60]; int uid; struct stack *prev; }; struct param { struct stack **elma; struct stack **elmb; }; struct stack *add(struct stack **base, char *line,int uid) { struct stack *element=(struct stack*)malloc(sizeof(struct stack)); element->prev=*base; strcpy(element->data,line); element->uid=uid; return element; } int search(struct stack *base,char *str) { while (base!=NULL) { if (strcmp(base->data,str)==0) return base->uid; base=base->prev; } return 0; } void * change(void *arg) { struct param *data=arg; *(data->elma) = add(data->elma, "chips", 5); *(data->elmb) = add(data->elmb, "volvo", 2); *(data->elma) = add(data->elma, "flips", 15); *(data->elmb) = add(data->elmb, "ford", 21); } int main() { int uid; pthread_t thread; struct stack *elma=NULL; struct stack *elmb=NULL; struct param arg; arg.elma=&elma; arg.elmb=&elmb; if (pthread_create(&thread, NULL, change, &arg) != 0) exit((puts("Can't create thread"), 1)); // тут делаете что-то полезное, \ пока не понадобятся данные из change() if (pthread_join(thread, 0)) exit((puts("Can't join"), 2)); uid=search(elma,"chips"); printf("chips: %i\n",uid); uid=search(elmb,"volvo"); printf("volvo: %i\n",uid); uid=search(elma,"flips"); printf("flips: %i\n",uid); uid=search(elmb,"bmw"); printf("bmw: %i\n",uid); } По сути, заменил передачу в change() указателей на "стеки" на передачу адресов этих указателей (структура param), поскольку в main Вы явно используете elma и elmb для обращения к search() и добавил вызов pthread_join для ожидания завершения заполнения "стеков" (естественно, добавил #include ). avp@wubu:hashcode$ gcc pt.c -lpthread && ./a.out chips: 5 volvo: 2 flips: 15 bmw: 0 avp@wubu:hashcode$

Ответ 2



Соберите указатели в одну структуру и передайте указатель на нее. Что-то типа struct param { struct strc * first; struct strc * second; }; struct param p; p.first = elma; p.second = elmb; и передавайте указатель на p. Примерно так.

Ответ 3



Не могу понять, как можно передать ссылки на эти 2 структуры в данную функцию (в потоке), Принципиальная разница между ПРОЦЕССОМ и ПОТОКОМ(нитью) заключается в том, что процессы работают в изолированных адресных пространствах, а все нити работают в одном(!) адресном пространстве. А это означает, что если Вы напишите вот так: struct data1 { . . . } struct data2 { . . . } void fun1(void *a) { . . . } void fun2(void *a) { . . . } То обе структуру данных будут видны в обоих функциях как глобально объявленные. И Вы можете запустить и ту и другую функцию как нити, не передавая в списках параметров вообще ничего. Существенно замечание: для того, что бы эти функции могли работать с ОБЩЕЙ структурой данных правильно, необходимо окружить эту работу защитными барьерами - мьютексами. Но это - отдельная тема.

Ответ 4



Используя предыдуший пример преобразуем чтобы было два массива typedef struct _data_s data_s; struct _data_s { int ready; int * first; int size_first; int * second; int size_second; }; static gpointer thread_fun(gpointer d) { int rc; data_s * data = (data_s*)d; int * first = data->first; int * second = data->second; int * local_first = g_slice_alloc0(sizeof(int)*data->size_first,); int * local_second = g_slice_alloc0(sizeof(int)*data->size_second);; for(;;){ /*чтение данных*/ rc = g_mutex_trylock(&mutex); if(rc){ rc = data->ready; if(rc){ memmove(local_first,first,data->size_first); memmove(local_second,second,data->size_second); data->ready = FALSE; g_mutex_unlock(&mutex); } else{ g_mutex_unlock(&mutex); g_usleep(10000); continue; } } else{ g_usleep(10000); continue; } /*обработка данных*/ .... /*запись данных*/ g_mutex_lock(&mutex); memmove(first,local_first,data->size_first); memmove(second,local_second,data->size_second); g_mutex_unlock(&mutex); /*если требуется накопление данных*/ g_usleep(TIMEOUT); } g_slice_free1(data->size_first,local_first); g_slice_free1(data->size_second,local_second); return NULL; int main(int argc,char * argv[]) { GThread * thread; data_s data; data.ready = FALSE; data.size_first = 10; data.first = g_slice_alloc0(sizeof(int)*data.size_first); data.size_second = 10; data.second = g_slice_alloc0(sizeof(int)*data.size_second); g_mutex_init(&mutex); thread = g_thread_new("data",thread_fun,&data); for(;;){ g_mutex_lock(&mutex); read(fd1,data.first,data.size_first); read(fd2,data.second,data.size_second); data.ready = TRUE; g_mutex_unlock(&mutex); } g_slice_free1(data.size_first,data.first); g_slice_free1(data.size_second,data.second); return 0; }

Комментариев нет:

Отправить комментарий