繁体   English   中英

如何在C中将GCD代码重写为POSIX

[英]How to rewrite GCD code as POSIX in C

这个问题是一个问题的后续问题,这个问题恰好比我原先想象的要复杂得多。 在一个程序中,我正在编写主线程处理GUI驱动的数据更新,一个生产者线程(有许多子线程,因为生产者任务是“令人尴尬的并行”)写入循环缓冲区,而真正的-time消费者线程从中读取。 原始开发平台是OSX / Darwin,但我想使代码更具可移植性,与UNIX源兼容。 一切都可以很容易地用POSIX编写,除了以下OSX特定的GCD命令,我无法估计POSIX等价物,如果有的话 它启动生成器线程,从中以编程方式启动其子线程,具体取决于可用的逻辑CPU核心数:

void dproducer (bool on, int cpuNum, uData* data)
{
    if (on == true)
    {
    data->state = starting;
         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            producerSum(on, cpuNum, data);
        });
    }
return;
}

这是该程序的框图:

在此输入图像描述

为清楚起见,我还添加了producerSum代码。 这是一个无限循环,其执行可以等待消费者线程完成工作,或者通过更改data-> state来中断,该状态具有全局范围:

void producerSum(bool on, int cpuNum, uData* data)
{
int rc;
pthread_t threads[cpuNum]; //subthreads
tData thread_args[cpuNum];
void* resulT;
static float frames  [4096];

while(on){
    memset(frames,  0, 4096*sizeof(float));
   if( (fbuffW  = (float**)calloc(cpuNum + 1, sizeof(float*)))!= NULL)
      for (int i=0; i<cpuNum; ++i){
        fbuffW[i] = (float*)calloc(data->frames, sizeof(float));
        thread_args[i].tid = i;           //ord. number of thread
        thread_args[i].cpuCount = cpuNum; //counter increment step
        thread_args[i].data = data;
        rc = pthread_create(&threads[i], NULL, producerTN, (void *) &thread_args[i]);
        if(rc != 0)printf("rc = %s\n",strerror(rc));
      }        
    for (int i=0; i<cpuNum; ++i) rc = pthread_join(threads[i], &resulT);
    //each subthread writes to fbuffW[i] and results get summed
    for(UInt32 samp = 0; samp < data->frames; samp++)
        for(int i = 0; i < cpuNum; i++)
            frames[samp] += fbuffW[i][samp];

    switch (data->state) { ... } //graceful interruption, resuming and termination mechanism

    { … } //simple code for copying frames[] to the circular buffer

    pthread_cond_wait (&cond, &mutex);//wait for the real-time consumer

    for(int i = 0; i < cpuNum; i++) free(fbuffW[i]); free(fbuffW);
} //end while(on)    
return;
}

生产者线程内部的同步由pthread_create()pthread_join()成功处理,而生产者和消费者线程之间的必要协调由pthread_mutex_t变量和pthread_cond_t变量(具有相应的锁定,解锁,广播)成功处理等待命令)。 uData是程序定义的struct(或类实例)。 任何指望的方向都会有所帮助。

感谢您阅读这篇文章!

调度队列正如它所说的那样:一个队列,就像在标准FIFO列表数据结构中一样。 它掌握着任务。 这些任务可以通过代码中的Objective-C Blocks或函数指针和上下文指针值来表示。 如果您的目标是跨平台兼容性,那么您可能需要避免使用Blocks。 事实上,由于您只调度一个任务,您的任务可以只封装参数( oncpuNumdata )而不是代码(对producerSum()的调用)。

队列由线程池中的线程提供服务。 GCD管理线程和池。 至少在OS X上,与操作系统集成,使得池的大小由整体系统负载控制,您将无法以跨平台方式重现。

调度队列上的操作是线程安全的。 这包括向他们添加任务以及工作线程从中删除任务。

你将不得不实施所有这些。 这绝对是可能的,但这将是一个麻烦。 在许多方面,队列和线程池构成了生产者 - 消费者体系结构。 基本上,您的基于GCD的解决方案有点作弊,因为您只是使用生产者 - 消费者API来实现您的生产者 - 消费者设计。 现在,你将不得不在没有拐杖的情况下真正实现生产者 - 消费者设计。

基本上没有比你已经使用的线程创建和POSIX条件变量更多的了。

dispatch_async()基本上只是锁定任务队列的互斥锁,将任务添加到队列,发出条件变量信号,并解锁互斥锁。 每个工作线程只会等待条件变量,当它唤醒时,锁定互斥锁,如果有任务,则从队列中弹出一个任务,解锁互斥锁,如果有任务则运行任务。 您可能还需要一种机制来向工作线程发出正确终止时间的信号。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM