Home | News | Documentation | Download

How to send a signal to ROOT from an external Thread?

Hello,
I would like to interrupt the event-loop of ROOT from an external thread in order to ask the Thread of ROOT to execute a given function. I don’t know exactly how to do this. Do i have to use a mutex? a condition variable?

I guess, the answer could be to use:

classTTimer.html

But this is not clear for me how to use TTimer from an external Thread.

Thanks,
Frédéric Faure.


Please read tips for efficient and successful posting and posting code

ROOT Version: Not Provided
Platform: Not Provided
Compiler: Not Provided


Hi Frederic,

IIUC you should be able to use just plain C++ for that, see e.g. https://stackoverflow.com/questions/41470942/stop-infinite-loop-in-different-thread

Does that do it?

Cheers, Axel.

Hi Axel,
thanks for your answer, that i read.
But sorry, i don’t see yet how to proceed. Suppose Root is in its loop. Then what to write in an external thread, to ask the Root’s thread to execute some function, (not leaving its loop)?
Cheers, Frédéric.

Hi Frederic,

The fact that it’s ROOT running something shouldn’t matter here, I guess? So you basically have

// thread1
while (true)
  do_something()
// thread 2
std::cin;
// somehow make thread1 do something

Did I get this right? Then:

std::atomic_bool print_token = ATOMIC_VAR_INIT(false); // ideally pass to thread1 by reference.
// thread1
while (true) {
  do_something();
  if (print_token) {
    print_info();
    print_token = false;
  }
}
// thread 2
while (true) {
  std::cin;
  print_token = true;
}

If this doesn’t answer it then I don’t understand what you try to do :slight_smile: I guess something that might be relevant is what exactly you mean by saying “Root is in its loop”?

Cheers, Axel.

Hi Alex,
thank you for your patience and your detailed answer. So that i can precise now my question. I understand your code above, and my problem is that the loop contained in the code that you call “thread1” above and that i call the “loop of root” is not visible for me: i guess it is starting with the command:
p_App->Run(); // with TApplication * p_App = new TApplication(“App”, nullptr, nullptr);
that i write but how (where) can i insert the following “test” ?:

if (print_token) {
    print_info();
    print_token = false;
  }

Do i have to write by myself (or derive) the function p_App->Run()?

For me the function p_App->Run() is useful and necessary because it waits for mouse/keyboards events and widget events on the GUI.

I hope that my question is more clear, or maybe i am missing what you want to explain.
Cheers,
Frédéric.

Hi Frederic,
Thanks, now I understand! Indeed a TTimer can work then, as it will be called by ROOT’s event loop, and allows you to act on print_token becoming true. Makes sense?
Cheers, Axel.

Hi Axel,
Yes i understand. So now my practical question please is:
i don’t know how to use TTimer for that purpose (i.e. interact with the ROOT loop thread from an external thread), because i don’t find examples in the documentation. What minimal code to write please using TTimer, for a call from an external thread (and not from ROOT’s event loop)?

Cheers,
Frédéric.

Hi Frederic,

Does tutorials/hist/hsumTimer.C help? Note that this is a terrible tutorial because it is thread-unsafe. But I did mention atomic_bool so I’m confident you know how to do the inter-thread communication correctly :slight_smile:

Cheers, Axel.

Hi Axel,
thank you,
in the example you gives:
https://root.cern.ch/doc/master/hsumTimer_8C.html
i understand that there is a periodic call from the ROOT loop to the external function hsumUpdate(), with period 300 msec.
I already used this way of doing, but now i wanted to avoid this because it consumes CPU if the call is not needed and that it may be not reactive enough if the period T is long (ex: 300ms = 0.3 sec is long for me) , so i wanted to replace that by a notification to the ROOT loop to make a call to the external function hsumUpdate() only when i need to. Does it make sense? Is it possible?
Thanks,
Frédéric.

Hi Frederic,
The function called by TTimer should check whether further processing is needed, else return. That’s still fairly cheap - what are your constraints? Do you see a slowdown? Even running it every 30ms should be fine?
Axel.

Hi Axel,
Yes this is fine. Periodic inspection every 30ms is good for my purpose. I will keep this way of doing. My initial question was about a way to avoid this periodic call like using a conditional variable and a notify between threads only when i need it (i.e. refreshing a picture in real time). But i realize that this may be not possible or at least easy.
Thanks for all,
Frédéric.

There might be a way, but in the end it’s going to be very similar: you need to hook into the event loop (GUI events, not HEP events), and check whether “now it’s needed”. The timer is just one way of doing that. If it’s not performant enough then let me know and we can try to find another way.