Problem with std::thread in ROOT

Hi, everyone. I ran over forum and saw few topics on the question, but none provided the complete information…
So, the question is similar to this topic https://root-forum.cern.ch/t/using-std-thread-in-root-6-00-00/17722.

I’m trying to use std::thread to perform some heavy calculations within the procedure of fitting histograms.
The code is the following:

    int trd;
    std::thread thr[THREADS]; /// THREADS is predef int
    for(trd=0; trd < THREADS; trd++)
      {
				thr[trd]=std::thread([trd, arg ](){
					globalarray[trd] = func(arg);
					});
        }

   for(trd=0; trd < THREADS; trd++)
     {
			thr[trd].join();
     }

When trying to join the 0-th thread I’m getting an error:

  joining 0 thread...
  terminate called after throwing an instance of 'std::system_error'
  what():  Invalid argument

Another problem is that I somehow cannot use ROOT::EnableThreadSafety(), getting an error, saying there is no such func in ROOT namespace.
As possible solution tried to preload libthread.so, which did not help.

Would be grateful for any hint on the solution to this.
Cheers,
Ivan

Your problem is probably not in the code shown here. What is “func” doing? Anything it shouldn’t?

If I complete your code with function bodys, it runs fine.

#include <iostream>
#include <thread>

constexpr auto THREADS = 5u;

int globalarray[THREADS] = {0};

int func(int x) { return x * 2; }

void testThread() {
    std::thread thr[THREADS]; /// THREADS is predef int
    for (auto trd = 0u; trd < THREADS; trd++) {
        int arg = trd;
        thr[trd] = std::thread([trd, arg]() { globalarray[trd] = func(arg); });
    }

    for (auto &t : thr)
        t.join();

    for (const auto &result : globalarray)
        std::cout << result << '\n';
}

Can you test if my code works for you? If not, which ROOT are you using? If it works, you need to check other code.

Hi Ivan,
note that @behrenhoff code introduces int arg = trd; which is not present in your original code making the lambda capture ill-formed.

ROOT::EnableThreadSafety is available for all installations of ROOT built with the -Dimt=ON option (which is the default since at least v6.10, as far as I know). Of course you also need #include "ROOT.h" to have the declaration available.

Why is it ill-formed? Could you give a hint which rule I am violating here? The variable arg was already in the original code, I had to define it somehow.

Sorry, my wording in the previous message is not clear. Your code is fine, Ivan’s code is not – arg is not defined there but he captures it anyway.

I just wanted to point that out, as it might be the cause of his compilation error.

Thanks for replies.
Dear behrenhoff, your code works fine. As the most probable source of the problem, I’m now trying to figure out the problem in my function.
This is actually quite cumbersome function, calculating few matrix elements and thus operating complex floats.

Dear eguiraud, thanks for your remark. My agr-s were properly defined, I just did not include that piece of code in my post.

As soon as I figure out the problem, I’ll respond here.
Thanks again!
Ivan

I’d try to use a gloabl std::mutex dangerousRootMutex; and then start locking suspicious code using a std::lock_guard<std::mutex> lock(dangerousRootMutex); - for example, protect everything that works with global variables like gDirectory. (and find a better name for dangerousRootMutex :grinning:)

Is there any documentation which functions are protected by ROOT::EnableThreadSafety? I tend to put a lock_guard around everything unless I know for sure that it is thread safe.

Hi,
I must be missing some pieces as I did not see any reference to data races in the original question :sweat_smile:

In any case I agree that we should document what is made thread-safe by EnableThreadSafety, I will raise the topic at the next meeting.

Ok, concerning original question. I managed to make things work.

The bug was stupid but not evident (as it is usual)):
one of the function parameters depends on the thread number and due to a typo in different program, this parameter ran out of it’s boundaries.

behrenhoff, eguiraud, thanks a lot for sparing your time on my problem!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.