I'm trying to create a preprocessing macro that allows code to be multithreaded or not depending on runtime variable. My first attempt was only a compile-time macro and worked, but the runtime version is not.
// Working compile-time version
#ifdef USE_MT
    #define MT_START(Thread)                              \
        std::atomic<bool> Thread ## Ret = true;           \
        std::thread Thread([&]()                          \
        {                                                 \
            std::atomic<bool> & __mtRet = Thread ## Ret;  \
            try{
    #define MT_END                                        \
            }catch(...){__mtRet = false;}                 \
    };
    #define MT_JOIN(Thread)                     \
        if (Thread.joinable()) Thread.join();   \
        if (Thread ## Ret){ throw; }
#else
    #define MT_START(Thread)
    #define MT_END
#endif
// Minimal use example
#define USE_MT
void function()
{
    int i = 0; 
    int j = 0;
    MT_START(th1)
    {
        i += 2;
        MT_START(th3)
        {
            i += 4;
        }
        MT_END;
        MT_JOIN(th3);
    }
    MT_END;
    MT_START(th2)
    {
        j += 2;
    }
    MT_END
    MT_JOIN(th1);
    MT_JOIN(th2);
}
Now here's the conditional version. I'm creating a lambda from user code and executing the lambda if the condition is false, otherwise I'm launching a thread with the lambda.
The main difficulty here is that the compile-time version is already widely in use on the project and I'm trying to change macro without rewriting all previous code (which leads to those __mt references)
#define MT_START(Thread, Cond)                           \
    std::thread Thread;                                  \
    std::atomic<bool> Thread ## Ret = true;              \
    {                                                    \
        auto & __mtTh = Thread;                          \
        const bool __mtCond = Cond;                      \
        auto __mtLambda = [&]() -> void                  \
        {                                                \
            std::atomic<bool> & __mtRet = Thread ## Ret; \
            try {
#define MT_END                                           \
            }catch(...){__mtRet = false;}                \
        };                                               \
        if (__mtCond)                                    \
        {                                                \
            __mtTh = std::thread{__mtLambda};            \
        }                                                \
        else                                             \
        {                                                \
            __mtLambda();                                \
        }                                                \
    }        
This last version makes unit tests to fail randomly, and I can't see why this last set of macros is different from the first one.
If anyone can help. Thanks
Aucun commentaire:
Enregistrer un commentaire