1

I have an application for which I code with Java and C++. In this application I need to have multiple "trials" that lasts exactly N seconds (let's say N = 15). What I also need is to log the current state every 0.005 seconds. For this exact purpose I have the following code:

std::thread timerTrial(&endTrial,this);
std::thread timerLog(&log,this);
std::thread timerTrial(&endTrial,this);
timerLog.detach();
timerTrial.detach();

void endTrial(){
    usleep(TIME);
    isOver = true ;
    //...
}

void log(){
    while(isOver == false){
        usleep(TIMELOG);
        //Do the logging
    }
}

The thing is when I'm looking at my logging (which is then written in a file) I see that I get a different number of logging lines (thus meaning that one trial has logs till 14.5 seconds for instance and the other 14.3 and an other one 14.8). Is there any way to improve this code so as to get less differences between each trial.

I think that the logging that I have to do in log() may be responsible for a small delay but honestly it is a really small logging (mainly adding things into a std::vector). Should I create an other parallel thread to do this logging as well so as not to waste time in my while loop in the log() function?

I'm running short of ideas to improve this code so as to decrease the difference between each trial. I hope my question is clear enough. If not feel free to comment to ask for further explanations.

Thanks in advance,

Peter G.
  • 14,786
  • 7
  • 57
  • 75
LBes
  • 3,366
  • 1
  • 32
  • 66
  • 1
    You may use a condition variable that is waited on in the beginning of both thread functions, and released from the main thread at a certain point of time. – πάντα ῥεῖ Aug 25 '16 at 17:14
  • @πάνταῥεῖ trying that ASAP – LBes Aug 25 '16 at 17:15
  • 4
    but even then... the determinism of thread pre-emption is entirely down to the scheduler in use. This is an OS question, not a language one. – Richard Hodges Aug 25 '16 at 17:15
  • Do not use threads at all. Schedule yourself –  Aug 25 '16 at 17:17
  • If using a CV, make sure you do a "signal all" of course. – flu Aug 25 '16 at 17:17
  • @DieterLücking not possible for me to go without threads. I definitely need threads as I have to do computation for the UI at the same time. I cannot afford any delay in the UI – LBes Aug 25 '16 at 17:19
  • @RichardHodges so you think there's no way to programatically make sure they run at the same time? – LBes Aug 25 '16 at 17:21
  • 1
    @LBes: The nature of threads is that they take turns at some point, either in processing or in data access. EDIT: Before people jump on me about pure parallelism and only reading data, what I mean is, OP has a UI thread and a data thread that sound like they both need to touch the same things. They're going to need to synchronize. – AndyG Aug 25 '16 at 17:26
  • 1
    The same problem, however Java only, was considered in question http://stackoverflow.com/questions/3376586/how-to-start-two-threads-at-exactly-the-same-time?rq=1 – Peter G. Aug 25 '16 at 17:27
  • 1
    @LBes I'm not saying no way, just that if there is a way, it lies in the API between your program and the particular OS you're running on. – Richard Hodges Aug 25 '16 at 17:28
  • Thanks everyone for your comments. Well the UI and these threads don't touch at the same variables so they should not take turn (UI thread and these two). Of course I'm open to a solution without any threads as one of you mentioned that, but I can't think of a way to make that happen. Perhaps however I could merge these two threads into a single one, but even that seems impossible to me. – LBes Aug 25 '16 at 17:31
  • `std::this_thread::sleep_until` seems more appropriate than `std::this_thread::sleep_for`, as if logging takes longer, you don't accumulate that time for next logs. – Jarod42 Aug 25 '16 at 17:36
  • @Jarod42 but I'm not using sleep_for currently – LBes Aug 25 '16 at 17:38
  • @PeterG. nice Java solution, but that does not work for me and has never been implemented in C++. Apparently it was a project for C++14 though – LBes Aug 25 '16 at 17:41
  • @LBes: `usleep` and `std::this_thread::sleep_for` are similar. I said that you must adjust the sleeping time. – Jarod42 Aug 25 '16 at 18:11
  • @Jarod42 changed from usleep() to sleep_until(). No change at all on my side. EDIT: apparently it did though. More tests on the way – LBes Aug 25 '16 at 18:20
  • @Jarod42 I'll test more tomorrow but it seems to have greatly decreased the difference. My maximum difference between two trials is now around 0.2 seconds instead of a previous maximum of 0.8. But then again that may be pure luck. What do you think? – LBes Aug 25 '16 at 18:27

1 Answers1

0

Turns out I have found a workaround that is doable without slowing the UI. I just combined this two threads together in a single thread with a for loop

Final code looks like something like this.

std::thread timerTrial(&endTrial,this);
//....
void endTrial(){
    int nbOfLogsNeeded = //Compute how many logs I will need during the time of trial
    for(int i = 0 ; i < nbOfLogsNeeded ; i++){
        std::this_thread::sleep_until(std::chrono::system_clock::now() + std::chrono::milliseconds(50));
        //Perform Logging
    }
}

It does not entirely answer the question but the workaround works just fine for me.

LBes
  • 3,366
  • 1
  • 32
  • 66
  • My comment about `sleep_until` is to compute only once `now`, and add the offset in the loop. As is, you might use `sleep_for`. – Jarod42 Aug 26 '16 at 13:22
  • I didn't says it doesn't work, but it is not natural and more complicated as needed. – Jarod42 Aug 26 '16 at 14:28