如何在不使用线程的情况下并发执行函数

时间:2014-09-27 18:37:36

标签: c++ c concurrent-programming

我有一个服务器程序将客户端的数据发送给另一个处理它的数据。但是因为函数可能需要很长时间才能执行并阻止程序处理其他客户端的数据,所以我希望在不使用pthread或创建进程的情况下同时对其他数据执行相同的函数。

我尝试创造一些可以做到这一点的东西,但它很丑陋,肯定不是最好的方法。这是我的代码:

#include <stdio.h>
#include <string.h>
#include <vector>

struct userdata {
    int rt; //The 'func' function uses it to resume work where it returned the last time
    int len; //The length of 'data'
    char data[16384]; //Client's data
};

int func(userdata *ud)
{
    //The gotos are here to jump to the code where the function returned the last time
    if(ud->rt==1)goto P1;
    if(ud->rt==2)goto P2;

    ud->len=0;

    //Code to calculate the length of 'data'
    while(ud->data[ud->len]!=0)
    {
        ud->rt=1; //Set to 1 to indicate where to resume execution the next time we will process the same data
        return 0;
        P1:
        ud->len++;
    }
    // Work
    ud->rt=2;
    return 0;
    P2:
    // Work

    return 1;
}

int main(int argc, char *argv[])
{
    userdata ud;
    memset(ud.data,1,16383);
    ud.data[16383]=0;

    std::vector<userdata> vec;
    for(int i=0;i!=200;i++)vec.push_back(ud); //Add 200 times the structure in the vector
    unsigned int Sz=vec.size(); //I'll use Sz in the for loop to avoid calling size()

    bool Loop=true;
    do
    {
        for(int i=0;i!=Sz;i++)
        {
            if( func(&vec.at(i))==1) //If the function returned 1 this means that there's no more work to do
            {
                printf("str length = %i\n",vec.at(i).len); //Display the result
                vec.erase(vec.begin() + i); //Remove element from vector because there's no more work to do
                i--, Sz--; //Decrement Sz (size of the vector) and i (vector index) to avoid out_of_range exception
                if(Sz==0)Loop=false; //If there are no elements in the vector, leave Loop
            }
        }
    }
    while(Loop);

    return 0;
}

这里的问题是这不是并发执行,我必须在结构中放置必须恢复到其最后状态的变量,当向量包含数千个元素时,这可能需要很长时间。

2 个答案:

答案 0 :(得分:1)

不要尝试编写自己的通用线程库,它会比pthreads更昂贵。相反,使用您特定问题的知识来分解问题。找到一个让意义的地方。

我假设您已经有一个主循环,只需要调用select / poll / epoll。如果您还没有超时,请开始使用一个,这样您就可以在堆中存储一组额外的,定时的偶数触发器。

然后在每次计算中,在一定次数的迭代之后停止调度函数+要调用的数据。使用当前时间(最后,而不是当前计时器事件开始运行的时间)。假设时间实际通过,计时器调度程序将在继续执行新计时器的下一步(大约是循环调度程序的行为)之前首先完成最旧计时器的所有计算。请注意,要使切片大小过小,否则任务切换开销将开始占主导地位。

根据您的问题集,如果关联的客户端死亡,您可能会或可能不想添加逻辑来取消任何即将推出的计时器。

答案 1 :(得分:0)

不要试图重新发明轮子。线程机制很难。无论你做什么都会比系统提供的更慢,更慢。

将数据复制进出函数使用的数据结构是一种奇怪的方法。你会把它放在哪里?正常的线程方法是每个线程有一个堆栈(每个线程都有一个调用堆栈和一个数据堆栈)。每个线程执行一个函数实例,如果在堆上分配内存,则每个问题实例都存储在不同的堆位置(因此每个线程中的堆栈和寄存器将包含指向不同堆区域的指针)。