I have a base class that can start background thread, and stop it when needed. That thread calls two virtual methods Open() and Close(). So all inherited classes can re-implement this methods, but not starting/stoping thread routine (it more difficult than in example). I want to follow RAII principle and start/stop thid thread in constructor/destructor of base class.
The problem is, that calling virtual methods in constructor/destructor is a bad practice and didn't work in my case. Here is a shot example of my problem:
#include <iostream>
#include <thread>
#include <atomic>
class Base {
public:
Base() {
bg_thread_ = std::thread([this] {
Open();
while(!is_stop_) {
// do stuff
}
Close();
});
}
~Base() {
is_stop_ = true;
if(bg_thread_.joinable()) {
bg_thread_.join();
}
}
private:
virtual void Open() {
std::cout << "Base open" << std::endl;
}
virtual void Close() {
std::cout << "Base close" << std::endl;
}
std::thread bg_thread_;
std::atomic<bool> is_stop_{false};
};
class Inherited : public Base {
virtual void Open() override {
std::cout << "Inherited open" << std::endl;
}
virtual void Close() override {
std::cout << "Inherited close" << std::endl;
}
};
int main() {
Inherited inherited;
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}
The output is:
Inherited open
Base close
And without sleep is:
Base open
Base close
My current approach is to call Start() method after constructor and Stop() before destructor, but I want solution with RAII.
void Start() {
bg_thread_ = std::thread([this] {
Open();
while(!is_stop_) {
// do stuff
}
Close();
});
}
void Stop() {
is_stop_ = true;
if(bg_thread_.joinable()) {
bg_thread_.join();
}
}
Aucun commentaire:
Enregistrer un commentaire