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