异步 return 尚未完全 "set up" (或处理)的结果(作为结构)的最佳方法是什么

Whats the best way to asynchronously return a result (as a struct) that hasn't been fully "set up" (or processed) yet

好吧,老实说,我已经尝试查找 "Asynchronous Functions in C"(结果仅适用于 C#),但我对 C 没有任何了解。所以我要在这里问一下,但如果有更好的,已经在 StackExchange 或你有什么问题上提问,请告诉我他们。

所以我正在自学并发和异步函数等等,所以我正在尝试创建自己的线程池。到目前为止,我仍处于计划阶段,我正在努力寻找一条清晰的前进道路,但我不想分发代码,我只想朝着正确的方向轻推(否则练习毫无意义)。

从实际上不是 "ready" 的函数异步 return 的最佳方法是什么?这样一来,它几乎会立即 return ,即使它当前正在处理用户指定的任务。 "task" 将是一个回调和参数,以适应所需的必要 pthread_t 参数,尽管我稍后会处理属性。函数 return 是一个名为 "Result" 的结构,它包含 void * return 值和一个名为 "ready" 的字节(无符号字符),它将保存值 0 和 1。所以虽然"Result" 不是 "ready",则用户不应尝试处理该项目。然后,如果用户 return 为 NULL,"item" 可以为 NULL,但 "ready" 让用户知道它已完成。

struct Result {
    /// Determines whether or not it has been processed.
    unsigned char ready;
    /// The return type, NULL until ready.
    void *item;
};

该结构并不真正完整,但它是体现我正在尝试做的事情的基本原型。不过,这并不是真正的问题,尽管如果方法不对请告诉我。

接下来我必须实际处理这件事,同时在一切完成之前不要阻塞。正如我所说,该函数将创建结果,然后异步处理它并立即 return(通过 returning 这个结果)。问题是异步处理。我正在考虑在 thread_pool 中生成另一个线程,但我觉得它缺少线程池的要点,因为它不再保持简单。

这就是我的想法(我觉得这太复杂了)。在函数 add_task 中,使用传递的 sub_process 结构生成一个新线程(线程 A),然后 return 未处理但已初始化的结果。在生成的线程中,它还会生成另一个具有原始回调和参数的线程(看到问题了吗?这是线程 B),将线程 A 与线程 B 连接起来以捕获它的 return 值,然后将其存储在结果的项目成员。由于结果将指向用户持有的完全相同的结构,因此这应该不是问题

我的问题是它产生了 2 个线程,而不是能够在 1 个线程中完成,所以我想知道我是否做错了并使事情复杂化。是有更好的方法吗? pthread 的库是否有一个函数可以为我异步执行此操作?无论如何,原型 Sub_Process 结构在下面。

/// Makes it easier than having to retype everything.
typedef void *(*thread_callback)(void *args);

struct Sub_Process {
    /// Result to be processed.
    Result *result;
    /// Thread callback to be processed
    thread_callback cb;
    /// Arguments to be passed to the callback
    void *args;
};

我做错了吗?我觉得我错过了 Thread_Pool 的全部要点。另一个问题是,有没有一种方法可以生成一个已创建的线程,但它正在等待而不做任何事情?我正在考虑通过让它们在处理函数中等待直到被调用来创建所有线程来处理这个问题,但我觉得这是错误的方法。

为了进一步阐述,我还将 post 我正在尝试的一些伪代码 here

备注:这个问题推荐我post这里回答,所以复制粘贴过来,有没有编辑错误的地方请教。

编辑:不再生成另一个线程,而是直接调用回调,因此另一个线程的额外开销应该不是问题。

我认为您的意图是线程将请求执行异步工作,然后继续自己执行一些不同的工作,直到它需要异步操作的结果才能继续。

在这种情况下,您需要一种方法让请求线程停止并等待 Result 准备就绪。您可以通过在 Result:

中嵌入互斥锁和条件变量对来做到这一点
struct Result {
    /// Lock to protect contents of `Result`
    pthread_mutex_t lock;
    /// Condition variable to signal result being ready
    pthread_cond_t cond;
    /// Determines whether or not it has been processed.
    unsigned char ready;
    /// The return type, NULL until ready.
    void *item;
};

当请求线程到达它需要异步结果的地步时,它使用条件变量:

pthread_mutex_lock(&result->lock);
while (!result->ready)
    pthread_cond_wait(&result->cond, &result->lock);
pthread_mutex_unlock(&result->lock);

您可以将其包装在等待结果可用的函数中,销毁互斥锁​​和条件变量,释放 Result 结构和 return 的 return 值.

处理完成后线程池thread中对应的代码为:

pthread_mutex_lock(&result->lock);
result->item = item;
result->ready = 1;
pthread_cond_signal(&result->cond);
pthread_mutex_unlock(&result->lock);

Another question is, is there a way to spawn a thread that is created, but waiting and not doing anything? I was thinking of handling this by creating all of the threads by having them just wait in a processing function until called, but I've a feeling this is the wrong way to go about this.

不,你走对了。让线程池线程等待某些工作可用的机制与上述相同 - 条件变量。