手动实现类似std::async与std::future的异步调用

C++11/C++14支持std::future和std::async的异步调用,这本来是一件特别令人兴奋的事情,但是偏偏在C4droid平台(GCC 5.3 -std=c++14)上future模板无法使用,仔细研究了一下,future模板只是被forward declaration一下,在<future>头文件178、179行有这么一行宏定义组合

#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \
  && (ATOMIC_INT_LOCK_FREE > 1)
1
在PC上的CodeBlocks中,_GLIBCXX_HAS_GTHREADS = 1,_GLIBCXX_USE_C99_STDINT_TR1 = 1,ATOMIC_INT_LOCK_FREE = 2。

但是到了C4droid上,ATOMIC_INT_LOCK_FREE = 1,这样future的实现(在这行的下面)就被宏注释掉了。所以future模板无法使用。

为了解决这个问题,尝试了一下几种方法:

Try 1

于是追踪ATOMIC_INT_LOCK_FREE这个定义,来到atomic_lockfree_defines.h中,发现定义:

#define ATOMIC_INT_LOCK_FREE		__GCC_ATOMIC_INT_LOCK_FREE

然而__GCC_ATOMIC_INT_LOCK_FREE这个变量并不存在于任何头文件中... 这个宏定义应该是编译器自己定义并掌握的。因此这种方法无法解决问题。

Try 2

把这个宏定义条件注释掉,直接越过定义,然而发现编译错误,exception_handle一类的东西,百度了一下,在头文件加了这么一行

#include <bits/exception_ptr.h>
然后直接编译错误... 第40行,看了一下原因...直接血崩,居然还是ATOMIC_INT_LOCK_FREE在作怪。

于是直接define ATOMIC_INT_LOCK_FREE 2

然而还是各种编译错误...

Try 3

从编译参数角度考虑,在stackoverflow上找到了一个类似的问题,上面说-march=armv6即可。于是我就在编译参数加了-march=armv6 (之前的修改恢复原样)。这次倒是没有提示编译错误,然而连接错误... 爆出各种链接器错误,真是醉人... 我估计是我的设备是armv7所以没办法连接...

Try 4

最后的尝试:换了一个编译器CppDroid,顺便吐槽一下:这东西安装完成之后200多MB,而且还要联网下载,下载失败了不能编译也不能运行.... 

试了半天.. 最后还是一样的不好使... ATOMIC_INT_LOCK_FREE还是1。



搞了半天,还是无法实现异步调用,然而最近需要这个功能所以只好自己去实现。

初步代码如下:

#define FUNCTION_STD(FuncName,args...) void FuncName(int* _buildin_trg,##args)
#define FUNCTION_START {
#define FUNCTION_END *_buildin_trg=1;}

#define NEWTHREAD(ThreadName,ThreadFunc,args...) _buildin_threadpack _buildin_threadpack_pack_##ThreadName(new thread(ThreadFunc,_buildin_threadpack_pack_##ThreadName.getpint(),##args))
#define ISOVER(ThreadName) (_buildin_threadpack_pack_##ThreadName.getint()==1)

class _buildin_threadpack
{
private:
    thread* s;
    int status;
public:
    _buildin_threadpack(thread* ins)
    {
        status=0;
        s=ins;
    }
    int getint()
    {
        return status;
    }
    int* getpint()
    {
        return &status;
    }
    ~_buildin_threadpack()
    {
        if(s!=nullptr)
        {
            s->join();
        }
        delete s;
    }
};
本来想使用shared_ptr这样的智能指针的,但是感觉不是特别好用,所以写了一个比较粗糙的类来包装thread.

示例代码如下:

FUNCTION_STD(func)
FUNCTION_START
cout<<"In func"<<endl;
FUNCTION_END


int main()
{
    NEWTHREAD(td,func);
    cout<<ISOVER(td)<<endl;
    this_thread::sleep_for(chrono::seconds(2));
    cout<<ISOVER(td)<<endl;
    return 0;
}

第一次isover返回0,第二次返回1

但是这个结构还没有考虑到FUNCTION异常退出等情况导致不能设置结束标记为1。对比future这个结构也没有wait_for和wait以及get调用。这些方法还是需要慢慢实现的。



你可能感兴趣的:(异步调用,C++11,stdfuture,C4droid)