#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; }
Комментариев нет:
Отправить комментарий