Assuming we have the classical Base class and derived class like this
class B {
public:
virtual ~B() {
// calling it here is too late, see explanations
//common_pre_cleanup_function();
}
void common_pre_cleanup_function() { }
};
class D : public B {
public:
virtual ~D() {
// What if we forget to do this call in another derived class?
common_pre_cleanup_function();
}
};
How would you make sure a function like common_pre_cleanup_function() is called in all derived Ds destructors before the members of D are destroyed but without having to explicitly call this function in every destructor-implementation of a new D?
Background
In my current project we have a base class that implements certain parallelism and threading features and will eventually start a new thread that does the actual work.
In the destructor of this base class we wanted to make sure, that the thread is always stopped and joined so that it gets cleaned up properly.
However derived classes may create members that are used by this thread in the base class. So if we destroy objects of the derived class, these members are also destroyed. But at this time the thread that is managed by the base class can still be running and now wrongfully access destroyed members.
I'm aware that this isn't the smartest approach to solve the issue and probably splitting up the threading/parallelisation parts and the "actual work" parts into separate classes might be the much smarter idea. However I'm interested if there are any approaches that don't involve an entire rewrite of the existing code base.
This code here is closer to our situation
class BackgroundTask {
public:
virtual ~BackgroundTask() {
// if we forget to call stop() in the derived classes, we will
// at this point have already destroyed any derived members
// while the thread might still run and access them; so how/where
// can we put this call?
//stop();
}
void stop() {
cancelFlag_.set();
thread_.join();
}
// more functions helping with Background tasks
private:
Thread thread_;
Condition cancelFlag_;
};
class MyTask : public BackgroundTask {
public:
virtual ~MyTask() {
// with the current case, we have to remember to call
// this function in all destructors in classes derived
// from BackgroundTask; that's what I want to avoid
stop();
}
private:
std::unique_ptr<MyClass> member;
};
Quite simply you don't. The best thing to do in this situation is to redesign how everything works to prevent this from being a problem.
But lets face it, in all likelihood you don't have the time and/or resources to achieve that. So your second best option (in my opinion) is to ensure that any call to the destroyed members of the derived class kills you application immediately with a very clear error message.
If a system must fail, fail early.
You might do something like:
template <typename TaskImpl>
class Task final : public TaskImpl
{
static_assert(std::is_base_of<BackgroundTask, TaskImpl>);
public:
virtual ~Task() { stop(); }
};
And then
class MyTaskImpl : public BackgroundTask
{
// ...
private:
std::unique_ptr<MyClass> member;
};
using MyTask = Task<MyTaskImpl>;
While I agree with comments that the design is flawed .....
Assuming that the objects are dynamically allocated, one solution is to make the destructors virtual and protected, and use a separate function to take care of calling the "pre-cleanup" before destroying the objects. For example;
class B
{
public:
void die()
{
common_pre_cleanup_function();
delete this;
};
protected:
virtual ~B() {};
private:
void common_pre_cleanup_function() { };
};
class D : public B
{
protected:
virtual ~D() {};
};
int main()
{
B *b = new D;
b->die();
}
This has a few limitations for the user of the class. In particular, behaviour is undefined if
the object is not created using a new expression;
any non-static member function of the object is called after calling die()
any non-static data member is accessed after calling die()
This also means that, if you maintain a set of objects (like a vector of pointers, B*) then it is necessary to remove the pointer from the list to ensure no usage of the object after it has died.
The protected destructors prevent a few things. Functions that are not members of friends of B or D cannot;
Create a B or a D of automatic storage duration
Use operator delete directly. For example, a statement delete b; in main() above will not compile. This also prevents destroying an object before calling the "pre-cleanup"
Edit: I realized this doesn't aswer your question but I'll leave it here for reference.
As mentioned earlier, each object should be responsible for managing its own resources so your design is a bit flawed to begin with.
Consider the following example. The TaskRunner is responsible for firing up a thread, and shutting it down when the constructor is called (textbook RAII). The Task class specifies what to do during the lifetime of the task, through pure virtual inheritance.
#include <atomic>
#include <future>
#include <iostream>
#include <memory>
struct Task {
virtual void run( ) = 0;
virtual ~Task( ) {
}
};
class TaskRunner final {
std::unique_ptr<Task> task;
std::future<void> fut;
std::atomic<bool> terminate;
public:
TaskRunner(std::unique_ptr<Task>&& task)
: task {std::move(task)}
, terminate {false} {
fut = std::async(std::launch::async, [this] {
while(!terminate) {
this->task->run( );
}
this->task.reset( );
});
}
TaskRunner(TaskRunner&&) = delete;
TaskRunner& operator=(TaskRunner&&) = delete;
TaskRunner(const TaskRunner&) = delete;
TaskRunner& operator=(const TaskRunner&) = delete;
~TaskRunner( ) {
terminate = true;
fut.wait( ); // Block until cleanup is completed
std::cout << "~TaskRunner()" << std::endl;
}
};
struct MyTask : public Task {
int i = 0;
void
run( ) {
// Do important stuf here, don't block.
std::cout << "MyTask::run() " << i++ << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds {100});
}
~MyTask( ) override {
// Clean up stuff here, run() is guaranteed to never be run again
std::cout << "~MyTask()" << std::endl;
}
};
int
main( ) {
TaskRunner t {std::make_unique<MyTask>( )};
std::this_thread::sleep_for(std::chrono::seconds {1});
}
Output
MyTask::run() 0
MyTask::run() 1
MyTask::run() 2
MyTask::run() 3
MyTask::run() 4
MyTask::run() 5
MyTask::run() 6
MyTask::run() 7
MyTask::run() 8
MyTask::run() 9
~MyTask()
~TaskRunner()
Related
I know that before the superclass ctor is finished, the subclass (and vtable) is not yet complete. But, I have a situation where, logically, I must be able to change the initialization of the superclass, and I'm trying to figure out how I can do that.
Here is a simplified example:
class Window {
std::thread uiThread;
void uiThreadProc(){
try {
UIInit();
NotifyOtherThreadThatUIInitFinished();
} catch(...){
UIClean();
throw; // actually using an exception_ptr but it's irrelevant here
}
EventLoop();
UICleanup();
}
virtual void UIInit();
virtual void UICleanup();
Super(){
CreateUIThread();
WaitForUIThreadToFinishUIInit();
}
~Super(){
SendQuitEventToUIThread();
WaitForUIThreadToFinish();
}
}
class Overlay : public Window {
Overlay(){
// can't do stuff before UIInit because Window ctor returns when UIInit finishes
}
void UIInit() override {
// won't be called because UIInit is called before Window ctor returns
}
void UIClean() override {
// won't get called if UIInit throws
}
~Overlay(){}
}
Currently, I'm trying to make it work by making the ctors private and moving the logic to an Init method that gets called after ctors, like this:
class Window {
static std::shared_ptr<Window> Create(){
auto window = std::make_shared<Window>();
window->Init();
return window;
}
virtual void Init() { /* actual ctor content here */ }
virtual void Cleanup() { /* actual dtor content here */}
bool cleanupCalled = false;
~Window(){
if(!cleanupCalled){
cleanupCalled = true; // with mutex and locks...
Cleanup();
}
}
}
class Overlay : public Window {
// same as above, but now overriding Init() and Cleanup()...
}
I assume this would work, but it feels super hacky and convoluted.
And I don't understand why this is the case from a design perspective, why don't ctors first create the complete vtable, then call the hierarchy of ctors? The vtable doesn't depend on member initialization, so it won't break things to do it first, correct?
Is this not a good use for inheritance?
I need to be able to override UIInit because some things must run on the UI thread. I could send it as functions/events and the EventLoop would execute that, but that would seriously break the logic of "when ctor finishes, the object is fully initialized", or if it absolutely has to run before the EventLoop. I could make my own thread event handling class, but that simply seems wrong for such a trivial case.
Any architectural suggestions are very welcome.
This can be solved by using composition instead of inheritance.
Furthermore, UIInit() and UICleanup() are begging to be RAII-driven. We can do this by separating Overlay in two types: The config, meant to live on the main thread, and a "Runtime" subtype that gets to live in the Window's thread.
#include <concepts>
#include <utility>
// Ignore these concepts pre-c++20
template<typename T, typename Owner>
concept WindowControllerRuntime = std::constructible_from<T, Owner*> &&
requires(T r) {
// Use this in lieu of pure virtual functions
{r.update()};
};
template<typename T>
concept WindowController = WindowControllerRuntime<typename T::Runtime, T>;
class Window {
public:
virtual ~Window() = default;
};
// pre-c++20: use template<typename ControllerT> instead
template<WindowController ControllerT>
class WindowWithController : public Window {
ControllerT controller_;
public:
WindowWithController(ControllerT controller)
: controller_(std::move(controller)) {
CreateUIThread();
WaitForUIThreadToFinishUIInit();
}
~WindowWithController() {
SendQuitEventToUIThread();
WaitForUIThreadToFinish();
}
void uiThreadProc(){
typename ControllerT::Runtime runtime(&controller_);
NotifyOtherThreadThatUIInitFinished();
EventLoop();
UICleanup();
}
private:
void SendQuitEventToUIThread();
void WaitForUIThreadToFinish();
void CreateUIThread();
void WaitForUIThreadToFinishUIInit();
void NotifyOtherThreadThatUIInitFinished();
void EventLoop();
void UICleanup();
};
// Usage example
#include <memory>
class Overlay {
public:
struct Runtime {
Runtime(Overlay* owner) {} // UIInit
~Runtime() {} //UIClean
void update() {}
};
};
int main() {
std::unique_ptr<Window> w = std::make_unique<WindowWithController<Overlay>>(Overlay{});
}
What I ended up using is this:
std::shared_ptr<Overlay> Overlay::Create() {
std::shared_ptr<Overlay> ptr(new Overlay(), [](Overlay* toDelete) {
toDelete->Cleanup();
delete toDelete;
});
ptr->Init();
return ptr;
}
But this has it's limitations:
I can't allocate an Overlay on the stack (because then I would have to call Init and Cleanup manually, and the whole point is to automate that).
I have to copy paste the Create method in every subclass of Window. Maybe there is a way to automate that with templates but I couldn't do it without making the whole class a template.
I'm not going to accept my answer just yet, maybe someone will have a better solution.
Opinion: I am a beginner in C++, but honestly, it seems to me like a huge design flaw not to be able to call virtual methods in the contructor/destructor. Other languages do it just fine (cough, Java, cough). And I don't see why it wouldn't work with a stack allocation as well as a heap allocation. You could literally do it manually (real ctor, fake ctor, dostuff, fake dtor, dtor) so the compiler could have done the same thing (allocate memory, fill vtable, ctor of base, ctor of sub, do stuff, dtor of sub, dtor of base, deallocate memory). And that way, the base can give a chance to the sub to do stuff before/after the base's ctor/dtor. But anyway, maybe there is some technical reason I'm missing.
Suppose I have the following code
#include <thread>
#include <iostream>
#include <atomic>
struct FooBase {
void start(){
run_condition_ = true;
t_ = std::thread([this](){
thread_handler();
});
}
virtual ~FooBase(){
run_condition_ = false;
if(t_.joinable())
t_.join();
}
protected:
virtual void thread_handler() = 0;
std::atomic_bool run_condition_{false};
private:
std::thread t_;
};
struct Foo : FooBase {
void thread_handler() override {
while(run_condition_){
std::cout << "Foo derived thread.." << std::endl;
}
}
};
int main(){
Foo f;
f.start();
getchar();
return 0;
}
Here I think because the destructor of the derived class Foo is called before FooBase the thread_handler vtable lookup happens in the base class IF the thread has not yet joined (still running) when the destructor of Foo is done. Since FooBase::thread_handler is pure virtual I am essentially guranteed a sigabort.
How do I guard against this? I hack my way through by not having thread_handler as pure virtual
virtual void thread_handler(){}
But I am lost as to how I can guard against this in the baseclass itself, I can implement a join_thread interface in the base class and call this from every derived class, but this seems cumbersome.
There's two issues here, neither of which match precisely what you described.
Your thread only gets stopped in ~FooBase(). This means that if Foo::thread_handler ever reads or writes to any of its members, they will get destroyed out from under it before the thread is stopped.
It you get to the destructor fast enough, it's possible that start() won't have actually invoked thread_handler() on the new thread by the time Foo gets destroyed - which will lead to the pure virtual call.
Either way, you need to ensure that by the time Foo is destroyed, anything related to thread_handler is done. This implies that every derived class from FooBase has to have, in its destructor:
run_condition_ = false;
if (t_.joinable()) {
t_join();
}
Setting aside that this directly doesn't work because t_ is private (you could wrap that into a protected stop()), it's an awkward design if all of your derived classes need to do something special just to work. You could instead put FooBase into its own class that just takes an arbitrary callable as an argument:
class joining_thread {
public:
joining_thread() = default;
~joining_thread() { stop(); }
bool running() const { return run_condition_.load(); }
template <typename... Args>
void start(Args&&... args) {
run_condition_ = true;
t_ = std::thread(std::forward<Args>(args)...);
}
void stop() {
run_condition_ = false;
if (t_.joinable()) t_.join();
}
private:
std::thread t_;
std::atomic_bool run_condition_{false};
};
And then your Foo can just have that as a member:
class Foo {
public:
void start() {
t_.start([this]{
while (t_.running()) { ... }
});
}
private:
// just make me the last member, so it's destroyed first
joining_thread t_;
};
That's still a little awkward with the whole running() thing, but hopefully the idea makes sense.
What you describe is not possible. You call "start" after you have constructed the object. The object is at that stage valid. You have avoided the common problem of calling a virtual function in the constructor, which would have caused issues. There is something called a memory barrier that is implied by any thread calls, so you can count on the fact the new thread will start with a view of memory that existed at the point it was created. Any thing that existed AND was not changed, is fine.
Your problem (as described in another answer) is that you can exit and destroy the object (and it's vtable), before the thread is complete.
The simplest fix for this is use a packaged task. Calling "get" on the future ensures the task is finished before you continue. Consider the code below
#include "stdafx.h"
#include <thread>
#include <iostream>
#include <atomic>
#include <future>
int main()
{
std::atomic<bool> stop{ false };
std::future<void> sync;
std::packaged_task<void()> task([&stop]()
{
while (!stop)
{
std::cout << "Running\n";
}
});
std::thread thread([&task]() {task();});
getchar();
stop = true;
task.get_future().get();
thread.join();
return 0;
}
I'd like to be able to group similar functions in a class into a group so I don't need to append each name with what it's about.
I've seen this question which says that you can't have namespaces within classes. I've also seen this question which proposes using strongly typed enums. The problem here though, is that I'm not sure whether or not these enums can actually accomodate functions?
The problem contextualised:
class Semaphore
{
public:
void Set(bool State){Semaphore = State;}
bool Get(){return Semaphore;}
void Wait()
{
while (Semaphore)
{
//Wait until the node becomes available.
}
return;
}
private:
bool Semaphore = 0; //Don't operate on the same target simultaneously.
};
class Node : Semaphore
{
public:
unsigned long IP = 0; //IP should be stored in network order.
bool IsNeighbour = 0; //Single hop.
std::vector<int> OpenPorts;
//Rest of code...
};
Currently, NodeClass.Get() is how I can get the semaphore. However this introduces confusion as to what Get() actually gets. I'd like to have something akin to NodeClass.Semaphore::Get(). Otherwise I'd have to have the functions as SemaphoreSet(), SemaphoreGet(), and SemaphoreWait(), which isn't too well organised or nice looking.
I had thought of just having the Semaphore class on it's own, and instantiating it within the other classes, but if I could stick with the inheritance approach, that would be nicer.
So essentially, is it possible to access inherited methods like InheritedClass.Group::Function()?
If you really want to do this, you could force the user to call with the base class name by deleteing the member function in the subclass:
class Base {
public:
void Set(bool) { }
};
class Derived : public Base {
public:
void Set(bool) = delete;
};
int main() {
Derived d;
// d.Set(true); // compiler error
d.Base::Set(true);
}
However, if the semantics of calling Set on the subclass are significantly different than what you'd expect them to be when calling Set on the base class, you should probably use a data member and name a member function accordingly as you've described:
class Base {
public:
void Set(bool) { }
};
class Derived {
public:
void SetBase(bool b) {
b_.Set(b);
}
private:
Base b_;
};
int main() {
Derived d;
d.SetBase(true);
}
I'm looking to run a thread in a base class that constantly calls pure virtual method in that class that's overridden by a derived class.
For starting the thread, I've no issue as I can call an HasInitalized() function after it's been constructed. Therefore the thread is started after the class is fully constructed.
However, as the class' lifetime is managed by a shared_ptr, I cannot call a similar method for stopping the thread. If I stop the thread in the destructor, it will cause a seg-fault as the derived class is destroyed before the base and therefore will try to call a function that's not there.
I'm aware I can call a stop function from the derived class but would rather not have to on every instance of the derived class.
Is there a way around this.
Example:
#include "boost/thread.hpp"
class BaseClass
{
public:
BaseClass()
{
}
// Start the thread
void Start()
{
_thread = boost::thread(&BaseClass::ThreadLoop, this);
}
virtual ~BaseClass()
{
_thread.interrupt();
_thread.join();
}
private:
// Will loop until thread is interupted
void ThreadLoop()
{
try
{
while(true)
{
DoSomethingInDerivedClass();
boost::this_thread::interruption_point();
}
}
catch(...)
{
}
}
boost::thread _thread;
protected:
virtual void DoSomethingInDerivedClass() = 0;
};
class DerivedClass : public BaseClass
{
DerivedClass()
{
}
~DerivedClass()
{
// This gets called before base class destructor.
}
protected:
void DoSomethingInDerivedClass();
};
I don't think you will be able to avoid repeating the call to join the thread in the destructor of each derived class. If a thread depends on a non-static object o, then it's a good idea to have a clear ownership relation to guarantee the validity of the object:
The thread should own o and the destruction of o will be handled by the destructor of the thread object, after the joining.
o should own the thread and should join the thread in it's own destructor.
You've chosen the 2nd approach, except the thread depends on the derived object, but the derived object doesn't own the thread directly but through the sub-object (the base-object). Since the thread depends on the derived object, it must be joined in the derived object's destructor.
You should separate the two behaviours: a class to run and join the thread, the base class for the functional hierarchy.
class Runner {
public:
explicit Runner(std::shared_ptr<BaseClass> ptr) : m_ptr(ptr) {
m_thread = boost::thread(&Runner::ThreadLoop, this);
}
~Runner() {
m_thread.interrupt();
m_thread.join();
}
private:
void ThreadLoop() {
try {
while(true) {
m_ptr->DoSomethingInDerivedClass();
boost::this_thread::interruption_point();
}
} catch(...) {
}
}
std::shared_ptr<BaseClass> m_ptr;
std::thread m_thread;
};
My recommendation would be to use a weak_ptr to know when the object's lifetime is over:
The factory instantiates the (derived) object and stores it in a shared_ptr
The factory instantiates the watchdog class and passes it a weak_ptr to the new object
The watchdog thread can now check if the weak pointer is expired each time it needs to access it. When it is expired, the thread will terminate itself.
Here is an example (instead of a factory, I just used main):
#include <thread>
class BaseClass
{
public:
virtual ~BaseClass() = default;
virtual void DoSomethingInDerivedClass() = 0;
};
class DerivedClass : public BaseClass
{
public:
void DoSomethingInDerivedClass() override {}
};
// Will loop until weak_base expires
void ThreadLoop(std::weak_ptr<BaseClass> weak_base)
{
try
{
while (true)
{
std::shared_ptr<BaseClass> base = weak_base.lock();
if (base) {
base->DoSomethingInDerivedClass();
}
else {
break; // Base is gone. Terminate thread.
}
}
}
catch (...)
{
}
}
int main()
{
std::shared_ptr<DerivedClass> obj = std::make_shared<DerivedClass>();
std::thread([&] { ThreadLoop(obj); }).detach();
return 0;
}
Note that there is no need to explicitly stop the thread, since it will stop itself as soon as it detects that the object's lifetime is over. On the other hand, note that the thread may slightly outlive the lifetime of the being-watchted object, which could be considered bad design (it could e.g. defer program termination). I guess one could work around that by joining with the thread in the base class destructor, after signalling that it should terminate (if not already terminated).
I have a class that has a Start method to start a thread that executes the virtual ThreadFunction at a predefined interval. The Stop method sets an event and waits until the the thread terminates (by a WaitForSingleObject on the thread handle).
In the destructor of MyThread, I call the Stop method. So whenever I delete the instance, I'm sure the thread is stopped before the delete returns.
class MyThread
{
void Start();
void Stop();
~MyThread() { Stop(); }
virtual VOID ThreadFunction() { }
};
Next I have a class that derives from MyThread:
class A : MyThread
{
virtual VOID ThreadFunction()
{
for (int i = 0; i < 1000; i++)
TestFunction();
}
void TestFunction() { // Do something }
};
Consider this code:
A a = new A();
a->Start();
delete a;
The problem is that delete a will first call the destructor of A before it will call the destructor of MyThread right? So if the thread was executing the for-loop in the ThreadFunction, the Stop method will be called after a has been destructed. This can lead to an access violation, when ThreadFunction calls TestFunction on a destructed instance.
A solution would be to add a destructor to class A that calls the Stop method, like this:
class A : MyThread
{
~A()
{
Stop();
}
}
But because I have a more complex class hiƫrarchy, that involves multiple inherited classes, this would mean I have to call the Stop method in each destructor, which would result in the Stop method being called plenty of times for only one instance that needs to be deleted.
Is there any other way to tackle this problem?
Your destructor in MyThread should be defined as 'virtual'.
class A{
public:
A(){cout<<"A"<<endl;}
virtual ~A(){cout<<"~A"<<endl;}
};
class B : public A{
public:
B(){cout<<"B"<<endl;}
~B(){cout<<"~B"<<endl;}
};
int main(){
A* b = new B();
cout<<"do something"<<endl;
delete b;
b = NULL;
return 0;
}
The result is:
A
B
do something
~B
~A
and when it doesn't use virtual, The result is:
A
B
do something
~A
As Rolle and R. Martinho Fernandes suggested, I needed to separate the two concerns.
class MyThread should not start or stop itself as its responsibility should be limited to the code it executes and not to the lifetime of the thread.
So the solution was to stop the thread from an other class (the same class that started the thread) which is responsible for the lifetime of the thread.