gpt4 book ai didi

c - 如何创建未定义数量的线程并在 Windows 上的 c 中使用 WaitForMultipleObjects()

转载 作者:行者123 更新时间:2023-11-30 19:33:04 24 4
gpt4 key购买 nike

PS:我对线程非常陌生。

我有一个问题,我需要等待来自客户端的连接请求(完全任意次数),接受套接字上的连接,连接后创建一个工作线程。创建的线程然后创建一个 char 数组,对其进行处理并需要将其传递给父进程。

我已经能够在 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()可用于将数据从线程传递到父进程(在unix中)。我的问题是,如何将其集成到主流程中的循环中。我预计以下方法将导致客户端和服务器之间一次只能建立一个连接的情况,这是不希望的。

 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() 的替代方案。 或其 Windows 等效项。

编辑:我知道 pthread_join() 适用于 Unix,并且已阅读 WaitForMultipleObjects() 是 Windows 的等效项。无论如何,我仍然无法找到解决方案。

最佳答案

I have seen that pthread_join() can be used to pass data from thread to parent process.

这并不完全正确。您可以在退出线程时传递一个指针,并使用 pthread_join 收集该指针。您必须自己实现所有逻辑。 API 不知道(或关心)指针是什么。线程没有 parent 和 child ,他们是 sibling 。

创造者和收割者的示例:

  • 全局

    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);
}
}
}

关于c - 如何创建未定义数量的线程并在 Windows 上的 c 中使用 WaitForMultipleObjects(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46400868/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com