• 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

  • 相关阅读:
    mobile app 的总结
    ie和火狐javascript区别
    zepto源码注释
    ie6bug
    html5游戏网站
    jquery作者封装函数
    vue element 动态表格
    uniapp 对 系统的控制,全屏,系统虚拟键盘,手机导航,强制横屏
    环形图表记录
    清除所有的滚动条
  • 原文地址:https://www.cnblogs.com/egametang/p/2466728.html
Copyright © 2020-2023  润新知