2017-09-25 22 views
-1

추신 : 나는 스레드에 매우 익숙하다.정의되지 않은 수의 스레드를 생성하고 윈도우의 c에서 WaitForMultipleObjects()를 사용하는 방법

클라이언트에서 연결 요청 (완전히 임의의 횟수)을 기다려야하고 소켓 연결을 수락하고 연결 후 작업자 스레드를 생성해야하는 등의 문제가 있습니다. 그런 다음 생성 된 스레드는 char 배열을 작성하여 작동하고 부모 프로세스에 전달해야합니다.

제가

while ((new_socket = accept(srv_sock, (struct sockaddr *)&client, &c)) != INVALID_SOCKET) 
{ 
    puts("\nConnection accepted"); 
    _beginthreadex(0, 0, handle_client, &new_socket, 0, 0); 

} 

I가 pthread_join()은 (UNIX)에서 상위 프로세스 스레드로부터 데이터를 전달하는데 사용될 수 있다는 것을 본 같이 while 루프에서 스레드를 생성 할 수 있었다. 내 질문은, 어떻게 그것을 주요 프로세스의 루프에 통합 할 수 있습니다. 다음 방법을 사용하면 클라이언트와 서버간에 한 번에 둘 이상의 연결을 설정할 수없는 상황이 발생할 것으로 예상됩니다.

while ((new_socket = accept(srv_sock, (struct sockaddr *)&client, &c)) != INVALID_SOCKET) 
    { 
     puts("\nConnection accepted"); 
     _beginthreadex(0, 0, handle_client, &new_socket, 0, 0); 
     pthread_join(thread_id,&my_array); 

    } 

편집 : pthread_join(). 또는 창에 해당 대안이 있다면 제가 원하는 것은 불가능한 경우, 또는 내가 아는하실 수 있습니다.

편집 : 나는 pthread_join()이 유닉스 용이고 해당 내용이 WaitForMultipleObjects()이며 windows에 해당한다고 읽었습니다. 어쨌든 나는 여전히 해결책을 찾을 수 없었습니다.

+0

는이 일의 '윈도우'방법은 내가 IOCP 완료 포트에서 대기하는 추측 것을 클라이언트 연결 수락 (겹쳐진 AcceptEx)과 클라이언트 스레드의 대기중인 메시지 (PostQueuedCompletionStatus) 모두. 양자 택일로, 다른 스레드에서 Accept() 루프를 실행하고 프로듀서 - 소비자 대기열 (아마도 PostMessage, GetMessage)에서 모든 것을 '주 스레드'(또는 모든 것을 관리하려고하는 모든 것)에 큐에 넣습니다. –

+0

TBH, 'join()'은 모든 경우에있어 약간의 PITA이며 가능한 경우 피하려고 노력해야합니다. 스레드가 끝날 때까지 기다릴 필요가 없도록 디자인 할 수 있다면 멀티 스레드 프로그래밍이 훨씬 쉬워지고 많은 고통을 피할 수 있습니다. 스레드의 수를 세는 데 의존하는 모든 디자인에도 동일하게 적용됩니다. 디자인은 중요하지 않으므로 걱정하지 않아도됩니다. –

답변

0

필자는 pthread_join()을 사용하여 스레드에서 부모 프로세스로 데이터를 전달할 수 있음을 확인했습니다.

완전히 정확하지 않습니다. 스레드가 일 때 포인터를 전달하고 pthread_join을 사용하여 해당 포인터를 수집 할 수 있습니다. 모든 논리를 직접 구현해야합니다. API는 포인터가 무엇인지 알지 못합니다. 실에는 부모와 자식이 없으며 형제입니다.

창조자와 사신의 예 :

  • 글로벌

    struct VarLengthArray { 
        size_t count; 
        MyElem data[1]; 
    }; 
    
  • 종료 스레드 :

    // allocate the result 
    size_t count = ...; 
    VarLengthArray *retval = malloc(
        sizeof(VarLengthArray) + 
        sizeof(MyElem) * (count > 0 ? count - 1 : 0) 
    ); 
    
    // fill the result 
    retval->count = count; 
    for (size_t i = 0; i < retval->count; ++i) { 
        retval->data[i] = ...; 
    } 
    pthread_exit(retval); 
    
  • 수집 스레드 :

    // collect the result 
    void *retval_; 
    if (pthread_join(thread_one_id, &retval_) != 0) { 
        // handle error 
    } 
    VarLengthArray *retval = retval_; 
    
    // use the result 
    for (size_t i = 0; i < retval->count; ++i) { 
        printf("retval->[%u] = %s\n", (unsigned) i, retval->data[i].string_value); 
    } 
    
    // deallocate the result 
    free(retval); 
    

조건 변수 여러 제작자가 사용하는 전체 예제 :

#include <limits.h> 
#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

typedef struct Datum { 
    struct Datum *next; 
    char some_data[32]; 
} Datum; 

typedef struct SharedData { 
    pthread_mutex_t mutex; 
    pthread_cond_t cond_empty; 
    unsigned seed; 
    Datum *head, *tail; 
    unsigned children_alive; 
} SharedData; 

static void *thread_logic(void *argv_); 

int main(int argc, char **argv) { 
    unsigned thread_count = 2; 
    if (argc > 1) { 
     if (sscanf(argv[1], " %u ", &thread_count) != 1) { 
      fprintf(stderr, "Usage: %s [thread_count]\n", argv[0]); 
      return 1; 
     } 
    } 

    // initialize shared data 
    SharedData shared_data; 
    pthread_mutex_init(&shared_data.mutex, NULL); 
    pthread_cond_init(&shared_data.cond_empty, NULL); 
    shared_data.seed = time(NULL); 
    shared_data.head = NULL; 
    shared_data.tail = NULL; 
    shared_data.children_alive = 0; 

    // start threads detached, so you don't have to call pthread_join 
    pthread_t *child_ids = malloc(sizeof(pthread_t) * thread_count); 
    pthread_attr_t attr; 
    pthread_attr_init(&attr); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 

    // start the threads 
    pthread_mutex_lock(&shared_data.mutex); 
    for (unsigned i = 0; i < thread_count; ++i) { 
     if (pthread_create(&child_ids[i], &attr, thread_logic, &shared_data) != 0) { 
      perror("pthread_create"); 
     } else { 
      ++shared_data.children_alive; 
     } 
    } 
    pthread_mutex_unlock(&shared_data.mutex); 

    pthread_attr_destroy(&attr); 

    // loop until all threads are dead 
    while (shared_data.children_alive > 0) { 
     // a condition variable: wait until there is data you can read 
     pthread_mutex_lock(&shared_data.mutex); 
     while (shared_data.head == NULL) { 
      pthread_cond_wait(&shared_data.cond_empty, &shared_data.mutex); 
     } 

     // collect a first datum 
     Datum *datum = shared_data.head; 
     if (datum->next != NULL) { 
      shared_data.head = datum->next; 
     } else { 
      shared_data.head = shared_data.tail = NULL; 
     } 

     pthread_mutex_unlock(&shared_data.mutex); 

     // handle the data (outside of the mutex lock) 
     printf("Got data: %s\n", datum->some_data); 
     free(datum); 
    } 

    return 0; 
} 

static void *thread_logic(void *shared_data_) { 
    SharedData *shared_data = shared_data_; 
    while (1) { 
     pthread_mutex_lock(&shared_data->mutex); 

     // create some data 
     useconds_t timeout = (
      (((float) (unsigned) rand_r(&shared_data->seed))/UINT_MAX) * 
      1000000 
     ); 
     Datum *datum = malloc(sizeof(Datum)); 
     datum->next = NULL; 
     if (timeout < 1000000/25) { 
      --shared_data->children_alive; 
      snprintf(datum->some_data, sizeof(datum->some_data), "I'm done\n"); 
     } else { 
      snprintf(
       datum->some_data, sizeof(datum->some_data), 
       "Sleeping for %uus\n", timeout 
      ); 
     } 

     // append the datum 
     if (shared_data->head) { 
      shared_data->tail->next = datum; 
     } else { 
      shared_data->head = datum; 
      pthread_cond_signal(&shared_data->cond_empty); 
     } 
     shared_data->tail = datum; 

     pthread_mutex_unlock(&shared_data->mutex); 

     // most likely it takes some time to create the data 
     // do lengthly tasks outside of the mutex lock 
     if (timeout < 1000000/25) { 
      return NULL; 
     } else { 
      usleep(timeout); 
     } 
    } 
} 
+0

루프에서 pthread_join()하는 방법? 또한 얼마나 많은 스레드가 만들어 졌는지 알지 못합니다. – George

+0

@ George, 내 답변을 업데이트하겠습니다 만, 몇 분이 걸릴 것입니다. 내가 끝나면 핑 소리내어. :) – kay

+0

@ 조지, 내 업데이트를 참조하십시오 – kay