2017-01-18 4 views
2

Хорошо или плохо создать поток в конструкторе объекта функции, передав разыменованный указатель this ссылкой на объект потока?Хорошо или плохо создать поток в конструкторе объектных объектов, передав разыменованный указатель `this` по ссылке на объект потока?

  1. Есть ли проблемы в приведенном ниже коде?
  2. Любые улучшения могут быть сделаны на нем, чтобы достичь цели ниже?

Цель состоит в том, чтобы изящно завершить поток, когда объект класса выходит за рамки.

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

class MyThread { 
private: 
    std::atomic<bool> exit; 
    std::thread t; 
public: 
    MyThread() : exit(false) { 
     t = std::thread(std::ref(*this)); 
    } 
    ~MyThread() { 
     exit.store(true, std::memory_order_relaxed); 
     if (t.joinable()) { 
      t.join(); 
     } 
    } 
    void operator()() { 
     while (!exit.load(std::memory_order_relaxed)) { 
      std::cout << "."; // some more meaningful work here 
      std::this_thread::sleep_for(std::chrono::seconds(1)); 
     } 
    } 
}; 

int main() { 
    MyThread t; 
    std::cin.get(); 
    return 0; 
} 

ответ

4

Возможно, это случается иногда, но это небезопасно. Это потенциально создает условие гонки, потому что вы начинаете поток на объекте, который еще не завершил свою конструкцию, что приводит к неопределенному поведению.

+3

В частности, это очень опасно, если в конструкторе выбрано исключение. – Frank

+1

@Frank это действительно важный случай, но я думаю, что есть и другие ситуации, достаточно, чтобы классифицировать шаблон как небезопасный вообще. –

+0

@ A.S.H Можете ли вы объяснить, почему запуск потока на объекте в конструкции приводит к неопределенному поведению? А где же состояние гонки? – etoricky