C++: C没有闭包真的很痛苦……

 

 

      我在上篇博客C++不是C/C++ 提到C++的std::function给C++带来了闭包。有人留言说:“没有闭包真的很痛苦吗?不见得吧!”。我的回答是:“是的,真的很痛苦。”

首先来看闭包的两个作用:1.打包上下文   2.延迟调用。我们来设计一个linux 线程池来说明闭包的价值。

      linux上线程创建的接口是:

int pthread_create(pthread_t*, const pthread_attr_t*, void *(*)(void *), void *params);

后面两个参数分别是一个函数指针,以及传给该函数的参数打包结构体的指针。上下文只能通过params结构体打包传入,以下代码只做使用说明,不保证正确性:

struct Params
{
    int a;
    double b;
};

void threadFunc(void* p)
{
    struct Params* params = (struct Params*)(p);
    ......
}

int f()
{
    int a = 1;
    double b = 2;
    Params params;
    params.a = 1;
    params.b = 2;
    pthread_create(&id, NULL, (void *)threadFunc, &params);
}

线程执行的函数需要在内部将传入的params强制转换成真正的类型,才能获取所需要的参数。

 

假设我们设计一个C的线程池,那么,我无法预计扔到线程池里面的函数是什么类型的,也不知道它的参数是什么结构的,所以接口设计也需要同pthread_create一样,传入一个void*(*)(void*)的函数指

针以及一个void* 类型的参数打包。接口可能设计如下:

void schedule(struct ThreadPool* threadPool, void *(*)(void *)f, void *params)

好了,假设我们程序中有个函数

    void Max(int a, int b, int* z)
    {
        *z = a > b? a : b;
    }

一个数组a[10000], 数组b[10000] ,数组c[i], 我要取得a[i] b[i]中较大者, 放入到c[i],代码可能如下(表明用法,不保证正确性):

struct MaxParam
{
    int a;
    int b;
    int* c;
};
void Max2(void* p)
{
    struct MaxParam* param = (struct MaxParam*)(p);
    Max(param->a, param->b, param->c);
}

void g()
{
    int a[10000];
    int b[10000];
    int c[10000];
    for (int i = 0; i < 10000; ++i)
    {
        MaxParam p;
        p.a = a[i];
        p.b = b[i];
        p.c = &c[i]; 
        schedule(&threadPool, (void *)Max2, &a); // 扔到线程池
    }
    wait(&threadPool); // 等待所有线程执行完成
}

可以看出,要重新定义一个新函数Max2和新的结构体MaxParam来配合线程池的使用, 代码中可能有千千万万的函数需要扔到线程池中执行,就要重新弄出千千万万个配合的函数和配合的结构体,

麻烦之极啊!

 

C++有了闭包会怎么做呢?接口就设计如下了:

class ThreadPool
{
    void schedule(std::function<void (void)> func);
    void wait();
};

接口简单清晰,使用起来方便极了,(代码只表示用法,不保证正确性):

    std::vector<int> x;
    std::vector<int> y;
    std::vector<int> z;
    for (int i = 0; i < 10000; ++i)
    {
        pool.schedule(
                std::bind(&Max, x[i], y[i], &z[i]));
    }
    pool.wait();

不用打包参数,也不需要搞个新函数配合线程池,用起来想出错真的很难啊!

 

C++一些复杂的设计是为了更加的简单!

可以看看boost threadpool 设计http://threadpool.sourceforge.net/,我写了一个例子如下

https://github.com/egametang/Egametang/blob/master/Cpp/Platform/Thread/ThreadPoolTest.cc

 

 

 

 

 

 

posted @ 2012-04-23 17:31  唐诗  阅读(7413)  评论(5编辑  收藏  举报