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

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM