Home > front end >  compiler optimisations and threads
compiler optimisations and threads

Time:01-30

I have a program that performs a task in a thread and I wanted to have the option to terminate early with a key-press. Here is a MWE:

#include <chrono>
#include <iostream>
#include <thread>

int main(int argc, char *argv[]) {
  char endChar = 0;// endChar is only written by keyboard thread
  std::thread kbth([&endChar]() { std::cin >> endChar; });//this thread monitors the keyboard
  kbth.detach();

  std::chrono::seconds run_t{15};
  bool running = true; // running could be written by main and task thread at
                       // same time (unlikely)
  std::mutex task_mtx; // so protect with mutex
  std::thread task([&running, &run_t, &task_mtx]() {
    std::this_thread::sleep_for(run_t);
    std::scoped_lock lock{task_mtx};
    running = false;
  });                                                   //this thread performs the task
  task.detach();

  while (running) {                                     //running is false when the task ends
    if (endChar == 42) { // 42=*
      std::cout << "key pressed" << std::endl;
      std::scoped_lock lock{task_mtx};
      running = false;                                  //or when * is entered 
      break;
    }
  }
  std::cout << "bye" << std::endl;
}

This works fine without compiler optimisations but fails with optimisations. Please can someone help me understand why this is happening? According to this compilers can optimise code as long as they don't change "the observable behavior of the program". So when this fails when optimisations are on doesn't this count as changing the observable behaviour? I tried with g and cl, summarised:

// clang-format off
// g   version 11.2.1 fedora 64bit
// g   -O0 -std=c  1z ../src/kbthread.cpp -o kbthread -l pthread //OK, exits gracefully when done or when key pressed 
// g   -O1 -std=c  1z ../src/kbthread.cpp -o kbthread -l pthread //fail, hang 
// g   -O2 -std=c  1z ../src/kbthread.cpp -o kbthread -l pthread //fail, hang

// cl version 19.29.30133 for x64 windows
// cl /EHsc -std:c  17 -Od -MD ../src/kbthread.cpp //OK, exits gracefully when done or when key pressed 
// cl /EHsc -std:c  17 -O1 -MD ../src/kbthread.cpp // fail, immediately prints "key pressed\nbye" 
// cl /EHsc -std:c  17 -O2 -MD ../src/kbthread.cpp // fail, immediately prints "key pressed\nbye"
// clang-format on

CodePudding user response:

OK, as comments below indicated threading issues @ François Andrieux I have "fixed" it using atomics with the code below:

int main(int argc, char *argv[]) {
  std::atomic_char endChar{0};
  std::thread kbth([&endChar]() { // this thread monitors the keyboard
    char buff = 0;
    std::cin >> buff;
    endChar = buff;
  });
  kbth.detach();

  std::chrono::seconds run_t{10};
  std::atomic_bool running{true};
  std::thread task([&running, &run_t]() { // this thread performs the task
    std::this_thread::sleep_for(run_t);
    running = false;
  });
  task.detach();

  while (running.load()) { // running is false when the task ends, so the program ends
    if (endChar.load() == 42) { // 42=*
      std::cout << "key pressed" << std::endl;
      running = false;     // or when * is entered, so the program ends early
      break;
    }
  }
  std::cout << "bye" << std::endl;
}

Still not sure about the use of detach but seems to work OK now.

  •  Tags:  
  • Related