In the following program I have a virtual call from within a thread:
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
class A {
public:
virtual ~A() { t.join(); }
virtual void getname() { std::cout << "I am A.\n"; }
void printname()
{
std::unique_lock<std::mutex> lock{mtx};
cv.wait(lock, [this]() {return ready_to_print; });
getname();
};
void set_ready() { std::lock_guard<std::mutex> lock{mtx}; ready_to_print = true; cv.notify_one(); }
void go() { t = std::thread{&A::printname,this}; };
bool ready_to_print{false};
std::condition_variable cv;
std::mutex mtx;
std::thread t{&A::printname,this};
};
class B : public A {
public:
int x{4};
};
class C : public B {
void getname() override { std::cout << "I am C.\n"; }
};
int main()
{
C c;
A* a{&c};
a->getname();
a->set_ready();
}
I was hoping the program would print:
I am C.
I am C.
But instead it prints:
I am C.
I am A.
In the program I wait until the derived object is fully constructed before I call the virtual member function. However the thread is started before the object is fully constructed.
How can the virtual call be assured?
The shown code exhibits a race condition, and undefined behavior.
In your main():
C c;
// ...
a->set_ready();
Immediately, after set_ready() returns, execution thread leaves main(). This results in immediate destruction of c, starting with the superclass C, and continuing to destroying B, then A.
c is declared in automatic scope. That means that as soon as main() returns, it's gone. Joined the choir invisible. It is no more. It ceased to exist. It's an ex-object.
Your join() is in the superclass's destructor. Nothing stops C from being destroyed. The destructor will only pause and wait to join the thread, when the superclass gets destroyed, but C will start getting destroyed immediately!
Once the C superclass is destroyed, its virtual method no longer exists, and invoking the virtual function will end up executing the virtual function in the base class.
Meanwhile the other execution thread is waiting on the mutex and the condition variable. The race condition is that you have no guarantee that the other execution thread will wake up and start executing before the parent thread destroys C, which it does immediately after signaling the condition variable.
All that signaling the condition variable gives you is that whatever execution thread is spinning on the condition variable, that execution thread will start executing. Eventually. That thread could, on a very loaded server, start executing seconds later, after its signaled via the condition variable. Its object is gone a long time ago. It was in automatic scope, and main() destroyed it (or, rather, the C subclass is already destroyed, and A's destructor is waiting to join the thread).
The behavior you are observing is the parent thread managing to destroy the C superclass before the std::thread gets around to making its virtual method call, after receiving the signal from the condition variable, and unlocking its mutex.
That's the race condition.
Furthermore, executing a virtual method call at the same time the virtual object is being destroyed is already a non-starter. It's undefined behavior. Even if the execution thread ends up in the overridden method, its object is being destroyed by another thread at the same time. You're pretty much screwed, at that point, no matter which way you turn.
Lessons learn: rigging up a std::thread to execute something in this object is a minefield of undefined behavior. There are ways of doing it correctly, but it's hard.
This is the most likely sequence of events:
The A part of the object is constructed, which starts a thread
The B part of the object is constructed.
The C part of the object is constructed.
getname is called on the main thread, which prints "I am C!" because it's a C.
The main thread notifies the other thread (I'll call it the printing thread)
main starts to return.
The C part of the object is destructed.
The B part of the object is destructed.
The A part of the object is destructed... but this blocks until the printing thread exits.
Now that the main thread is blocked the OS switches to the printing thread.
The printing thread calls getname, which prints "I am A!" because it's an A (with the C and B parts of the object now having been destroyed).
The printing thread exits
The main thread wakes up, finishes destroying the A part, and exits the program.
To get the expected behaviour reliably, you need to wait for the printing thread to exit before the closing } of main.
The other answers are definitive, but don't show a possible fix. Here is the same program with additional variables and waiting:
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
class A {
public:
virtual ~A() { t.join(); }
virtual void getname() { std::cout << "I am A.\n"; }
void printname()
{
std::unique_lock<std::mutex> lock{mtx};
cv.wait(lock, [this]() {return ready_to_print; });
getname();
printing_done = true;
cv.notify_one();
};
void set_ready() { std::lock_guard<std::mutex> lock{mtx}; ready_to_print = true; cv.notify_one(); }
void go() { t = std::thread{&A::printname,this}; };
bool ready_to_print{false};
bool printing_done{false};
std::condition_variable cv;
std::mutex mtx;
std::thread t{&A::printname,this};
};
class B : public A {
public:
int x{4};
};
class C : public B {
public:
~C()
{
std::unique_lock<std::mutex> lock{mtx};
cv.wait(lock, [this]() {return printing_done; });
}
void getname() override { std::cout << "I am C.\n"; }
};
int main()
{
C c;
A* a{&c};
a->getname();
a->set_ready();
}
Prints:
I am C.
I am C.
Related
Considering the following code, where I declare a simple class for executing asynchronous/threaded operations:
#include <chrono>
#include <thread>
#include <mutex>
#include <future>
#include <iostream>
using namespace std::chrono_literals;
class basic_executor {
public:
basic_executor() {
_mx.lock();
printf("Ctor #%p\n", this);
_mx.unlock();
}
virtual ~basic_executor() {
_mx.lock();
printf("Dtor #%p\n", this);
_mx.unlock();
if (_thread.joinable()) {
_thread.join();
_mx.lock();
printf("Joined thread #%p\n", this);
_mx.unlock();
}
}
// sync call
void run() {
start();
execute();
stop();
}
// async call
void launch(bool detach = false) {
// create packaged task
std::packaged_task< void() > task([this] {
start();
execute();
stop();
});
// assign future object to function return
_done = task.get_future();
// launch function on a separate thread
_thread = std::thread(std::move(task));
// detach them from main thread in order to avoid waiting for them
if (detach == true) {
_thread.detach();
}
}
// blocking wait for async (detached/joinable)
void wait() const {
_done.wait();
}
protected:
virtual void start() { /* for derived types to implement */ }
virtual void stop() { /* for derived types to implement */ }
virtual void execute() { /* for derived types to implement */ }
std::mutex _mx;
std::thread _thread;
std::future< void > _done;
};
And using the following application example where I derive from it to create two logger objects that make dummy prints for a certain span of time:
class logger : public basic_executor {
public:
logger() { /* ... */}
~logger() {
_mx.lock();
std::cout << "logger destructor " << std::endl;
_mx.unlock();
}
void execute() override {
std::this_thread::sleep_for(1s);
for (int i = 0; i < 10; ++i) {
_mx.lock();
printf("L1: I am printing something\n");
_mx.unlock();
std::this_thread::sleep_for(1s);
}
}
void stop() override {
_mx.lock();
printf("L1: I am done!\n");
_mx.unlock();
}
};
class logger2 : public basic_executor {
public:
logger2() { /* ... */}
~logger2() {
_mx.lock();
printf("logger2 destructor\n");
_mx.unlock();
}
void execute() override {
for (int i = 0; i < 10; ++i) {
_mx.lock();
printf("L2: I am ALSO printing something\n");
_mx.unlock();
std::this_thread::sleep_for(2s);
}
}
void stop() override {
_mx.lock();
printf("L2: I am done!\n");
_mx.unlock();
}
};
int main(int argc, char const *argv[]) {
/* code */
// printf("log:\n");
logger log1;
// printf("log1:\n");
logger2 log2;
printf("----------------------------------!\n");
log2.launch();
log1.launch();
// log1.wait();
// log2.wait();
printf("----------------------------------!\n");
return 0;
}
I am getting an unexpected behavior from the program:
Ctor #0x7fff8b18c990
Ctor #0x7fff8b18c9e0
----------------------------------!
----------------------------------!
logger2 destructor
Dtor #0x7fff8b18c9e0
Joined thread #0x7fff8b18c9e0
logger destructor
Dtor #0x7fff8b18c990
L1: I am printing something
L1: I am printing something
L1: I am printing something
L1: I am printing something
L1: I am printing something
L1: I am printing something
L1: I am printing something
L1: I am printing something
L1: I am printing something
L1: I am printing something
Joined thread #0x7fff8b18c990
in that occasionally, the 'log2' object never starts its execution before being destroyed, or the 'join()' call on its destructor hangs indefinitely. Is there any obvious reason why this happens, what exactly am I missing here?
The bug can occur with either logging class. However, with undefined behavior you have no guarantees whatsoever, and no expectation of any kind of consistent results. You've only, so far, observed the same bug with one of two logging classes. Although I can explain why is that, in practical terms, it is immaterial. The bug can happen with either of the objects. Let's begin here:
_thread = std::thread(std::move(task));
You are not going to get any guarantees whatsoever that the new execution thread will immediately start executing any of the following before this code proceeds and returns from launch():
std::packaged_task< void() > task([this] {
start();
execute();
stop();
});
Most of the time, practically, this is going to start running pretty quickly, in the new execution thread. But you cannot rely on that. All that C++ guarantees you is that at some point after std::thread finishes constructing a new execution thread will start running. It may be immediate. Or, it may be a few hundred milliseconds later because your operating system had something more important on its plate.
You are expecting that the new execution thread will always start executing "immediately", simultaneous with std::thread getting constructed. That is not true. After all, you might be running with a single CPU core, and after constructing the std::thread object you're continuing to execute what follows in the same execution thread, and only a while later a context switch occurs, to the new execution thread.
Meanwhile:
launch() returns.
The parent execution thread reaches the end of main().
All of the objects in the automatic scope are going to get destroyed, one by one.
In C++, when an object consists of a superclass and a subclass, the subclass gets destroyed first, followed by the superclass. This is how C++ works.
So, the logger/logger2 subclass's destructor gets immediately invoked and it destroys the its object (just the logger/logger2 subclass).
Now the superclass's destructor gets invoked, to destroy the superclass. ~basic_executor starts doing its thing, patiently waiting.
And now, finally, that new execution thread, remember that one? Guess what: it finally starts running, and valiantly tries to execute start(), execute(), and stop(). Or maybe it managed to get through start(), first, but hasn't reached execute() yet. But since the actual logger subclass is already destroyed now, guess what happens? Nothing. It's gone. The subclass is no more. It ceased to be. It joined the choir invisible. It is pining for the fjords. It's an ex-subclass. There is no logger::execute or logger2::execute() any more.
I am finding it very strange. Please, help me to explain this. I have a class which starts infinite loop in a separate thread, and two classes which inherit it. One of the classes implements the interface to be triggered outside as std::shared_ptr, and another one class hold this interface as std::weak_ptr. Please look at the code below. Sorry for a lot of code, I was trying to be as short as it possible to reproduce the error. Why sometimes have I pure virtual call in Sender::notify function? As far as I know std::shared_ptr is reentrant.
#include <iostream>
#include <memory>
#include <thread>
#include <atomic>
#include <list>
#include <mutex>
class Thread : private std::thread {
std::atomic_bool run {true};
public:
Thread() : std::thread([this](){ thread_fun(); }) {}
void thread_fun() {
while (run) loop_iteration();
}
virtual void loop_iteration() = 0;
virtual ~Thread() {
run.exchange(false);
join();
std::cout << "Thread released." << std::endl;
}
};
class Sender : public Thread {
public:
class Signal{
public:
virtual void send() = 0;
virtual ~Signal(){}
};
void add_receiver(std::weak_ptr<Signal> receiver) {
std::lock_guard<std::mutex> lock(receivers_mutex);
receivers.push_back(receiver);
}
void notify() {
std::lock_guard<std::mutex> lock(receivers_mutex);
for (auto r : receivers)
if (auto shp = r.lock())
shp->send(); //Somethimes I get the pure virtual call here
}
private:
std::mutex receivers_mutex;
std::list<std::weak_ptr<Signal>> receivers;
void loop_iteration() override {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
notify();
}
};
class Receiver : public Thread, public Sender::Signal {
std::atomic_bool notified {false};
public:
void send() override {
notified.exchange(true);
}
private:
void loop_iteration() override {
std::this_thread::sleep_for(std::chrono::milliseconds(250));
std::cout << "This thread was " << (notified? " " : "not ") << "notified" << std::endl;
}
};
int main() {
std::shared_ptr<Thread>
receiver = std::make_shared<Receiver>(),
notifier = std::make_shared<Sender>();
std::dynamic_pointer_cast<Sender>(notifier)->add_receiver(
std::dynamic_pointer_cast<Sender::Signal>(receiver));
receiver.reset();
notifier.reset();
return 0;
}
Polymorphism doesn't work as you may expect during construction and destruction. The current type is the most derived type that still exists. When you are in Thread::~Thread the Sender part of your object has already been completely destroyed so it wouldn't be safe to call its overrides.
When thread_fun tries to run loop_iterator() before the constructor finishes or after the destructor starts, it will not polymorphically dispatch, but instead it will call Thread::loop_iteration which is a pure virtual function (= 0).
See https://en.cppreference.com/w/cpp/language/virtual#During_construction_and_destruction
Here is a demonstration of this : https://godbolt.org/z/4vsPGYq97
The derived object is destroyed after one second, at which point you see the output change indicating that the virtual function being called changes at that point.
I'm not sure if this code is valid, or if destroying the derived part of the object while one of its member function is being executed is Undefined Behavior.
In addition to what François Andrieux noted, your real problem is that you are starting the thread running, using this object, before its construction is finished. It may or may not see the derived type constructed yet, depending on timing.
It's not calling thread_fun from the constructor, as he implies. It's calling that on a different thread, at some unknown point in the future. It might happen on a different core before this base class constructor has returned, or at any other random point during the derived class's construction process, or much later.
You can't safely start the thread's function until the object is ready to be used.
Separate creation from making it go. That's the easiest thing.
meanwhile
virtual ~Signal(){}
Don't define empty destructors. Write =default instead.
But, use override in the derived class, and don't use virtual there.
You have a problem in that you assume that the spawned thread does not start immediately and the current thread has time to initialize the state of the current object before it does anything.
This does not hold which causes two issues.
You accesses state in the current object that has not been initialized.
You use a polymorphic function that is not guranteed to work until after the object is fully constructed.
You make a slight assumption in your destructor:
You inherit from an object that does not have a virtual destructor.
Your thread may still accesses state after the object has started its destruction. If it does (access destroyed) then it is UB. Your thread needs to be able to check if the current object state is valid (i.e. All derived classes must get a lock on run and make sure its state is till true and all destructors must set run to false.
Your problem lies here:
class Thread : private std::thread {
std::atomic_bool run {true};
public:
Thread()
// Here you are starting a separate thread of execution
// That calls the method thread_fun on the current object.
//
// No problem so far. BUT you should note that "this" object
// is not fully constructed at this point and there is no
// guarantees that the thread you just started will wait
// for this thread to finish before doing anything.
: std::thread([this](){ thread_fun(); })
{}
void thread_fun() {
// The new thread has just started to run.
// And is now accessing the variable `run`.
//
// But `run` is a member and initialized after
// the base class so you have no idea if the parent
// thread has correctly initialized this variable yet.
//
// There is no guratnee that the parent will get to
// the initialization point of `run` before this new thread
// gets to this point where it is using it.
while (run) {
// Here you are calling a virtual function.
// The trouble is that virtual functions are not
// guranteed to work as you would expect until all the
// constructors of the object have run.
// i.e. from base all the way to most derived.
//
// So you not only have to wait for this base class to
// be full constructed you must wait until the object
// is full constructed before you call this method.
loop_iteration();
}
}
virtual void loop_iteration() = 0;
virtual ~Thread() {
// You have a problem in that std::thread destructor
// is not virtual so you will not always call its destructor
// correctly.
//
// But lets assume it was called correctly.
// When you get to this point you have destroyed the
// the state of all derived parts of your object.
// So the function your thread is running better
// not touch any of that state as it is not all invalid
// and doing so is UB.
//
// If your object had no state then you are fine.
run.exchange(false);
join();
std::cout << "Thread released." << std::endl;
}
};
I think a better solution is to make the std::thread a member of your object, and force any threads to hold until you have the state correctly initialized (at the point where you create the object).
class Thread {
std::atomic_bool run;
std::thread thread;
public:
Thread(std::function<void>& hold)
// Make sure run is initialized before the thread.
: run{false}
, thread([this, &hold](){ thread_fun(hold); })
{}
void thread_fun(std::function<void>& hold) {
// Pass in a hold function.
// The creator of your objects defines this
// It is supposed to make objects created until you
// have all the state correctly set up.
// once it is you allow any threads that have called
// hold to be released so they can execute.
hold();
while (run) loop_iteration();
}
virtual void loop_iteration() = 0;
virtual ~Thread() {
run.exchange(false);
join();
std::cout << "Thread released." << std::endl;
}
};
Then you can create a simple barrier to use in hold:
class Barrier
{
bool threadsShouldWait = true;
std::conditional_variable cond;
std::mutex mutex;
void wait() {
std::unique_lock<std::mutex> lock(mutex);
cond.wait([&](){return !threadsShouldWait;}, lock);
}
void release() {
std::unique_lock<std::mutex> lock(mutex);
threadsShouldWait = false;
cond.notify_all();
}
}
int main()
{
// Note you don't need to use the same barrier for
// both these variables. I am just illustrating one use case.
Barrier barrier;
std::shared_ptr<Thread> receiver = std::make_shared<Receiver>([&barrier](){barrier.wait();});
std::shared_ptr<Thread> notifier = std::make_shared<Sender>([&barrier](){barrier.wait();});
barrier.release();
I have a class which has a std::thread member. I detach it in the constructor, and I wanted to be sure that, when the object is destroyed, the thread is stopped and destroyed too.
How can I achieve this?
I have a class which has a std::thread member
Okay!
I detach it in the constructor
Alright. That means you don't want the class to manage the thread any more. No problem.
and I wanted to be sure that when the object is destroyed, the thread is stopped and destroyed too
Oh, so… huh. You do want the class to manage the thread? Interesting.
Don't detach the thread.
It is literally the anti-what-you-want-to-do and single-handedly responsible for your problem.
Once you detach a std::thread you no longer have control of that thread. the std::thread object releases it and all the resources of the thread will not be freed until the thread finishes or the process(program) exits. If you want to stop a detached thread you would have to send a signal to it with some sort of flag(std::atomic<bool> comes to mind) or std::condition_variable to have it end itself.
If you want the thread to live with the class and then once the class is destroyed then terminate the thread then you do not want to call detach. Instead what you would do is call join() in the destructor which stops the destructor from running until the thread finishes. Once it does then the destructor will continue and you will know that the thread has ended and everything has been cleaned up.
Let's see through an example how can an std::thread be handled to be ensured that will be stopped and destroyed when the enclosure object is destroyed:
#include <mutex>
#include <condition_variable>
#include <thread>
#include <atomic>
#include <cstdlib>
#include <ctime>
#include <iostream>
class ThreadTester {
public:
ThreadTester() : isAlive(true), randomNumber(0) {
// Start the background operation.
myThread = std::thread(&ThreadTester::createRandom, this);
}
virtual ~ThreadTester() {
{
// Stop the running thread.
std::unique_lock<std::recursive_mutex> lk(mutex);
isAlive = false;
condition.notify_all();
}
// Join the stopped thread.
if(myThread.joinable())
myThread.join();
}
int getRandom() const {
return randomNumber;
}
private:
void createRandom() {
std::unique_lock<std::recursive_mutex> lk(mutex);
// Do something with 250ms intervall while the isAlive is true.
while(isAlive) {
condition.wait_for(lk, std::chrono::milliseconds(250));
if(isAlive) {
randomNumber = rand() % 100;
}
}
}
std::recursive_mutex mutex;
std::condition_variable_any condition;
bool isAlive;
std::thread myThread;
std::atomic_int randomNumber;
};
int main() {
srand(time(NULL));
const ThreadTester tester;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Test: " << tester.getRandom() << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Test: " << tester.getRandom() << std::endl;
return 0;
}
I my example I hold the thread until it become stopped to make it sure it can be destroyed safely. I don't think so that detaching a thread is a good practice.
If I spin off an std::thread in the constructor of Bar when does it stop running? Is it guaranteed to stop when the Bar instance gets destructed?
class Bar {
public:
Bar() : thread(&Bar:foo, this) {
}
...
void foo() {
while (true) {//do stuff//}
}
private:
std::thread thread;
};
EDIT: How do I correctly terminate the std::thread in the destructor?
If I spin off an std::thread in the constructor of Bar when does it
stop running?
the thread will run as long as it executing the callable you provided it, or the program terminates.
Is it guaranteed to stop when the Bar instance gets destructed?
No. In order to guarantee that, call std::thread::join in Bar destructor.
Actually, if you hadn't call thread::join or thread::detach prior to Bar::~Bar, than your application will be terminated by calling automatically to std::terminate. so you must call either join (preferable) or detach (less recommended).
you also want to call therad::join on the object destructor because the spawned thread relies on the object to be alive, if the object is destructed while your thread is working on that object - you are using destructed object and you will have undefined behavior in your code.
Short answer: Yes and no. Yes, the thread ends, but not by the usual way (killing the thread), but by the main thread exiting due to a std::terminate call.
Long answer: The thread can only be safely destructed when the underlying function (thread) has finished executing. This can be done in 2 ways
calling join(), which waits for the thread to finish (in your case, never)
calling detach(), which detaches the thread from the main thread (in this case, the thread will end when the main thread closes - when the program terminates).
If the destructor is called if all of those conditions don't apply, then std::terminate is called:
it was default-constructed
it was moved from
join() has been called
detach() has been called
The C++ threading facilities do not include a built-in mechanism for terminating a thread. Instead, you must decide for yourself: a) a mechanism to signal the thread that it should terminate, b) that you do not care about the thread being aborted mid-operation when the process terminates and the OS simply ceases to run it's threads any more.
The std::thread object is not the thread itself but an opaque object containing a descriptor/handle for the thread, so in theory it could be destroyed without affecting the thread, and there were arguments for and against automatic termination of the thread itself. Instead, as a compromise, it was made so that destroying a std::thread object while the thread remained running and attached would cause the application to terminate.
As a result, In it's destructor there is some code like this:
~thread() {
if (this->joinable())
std::terminate(...);
}
Here's an example of using a simple atomic variable and checking for it in the thread. For more complex cases you may need to consider a condition_variable or other more sophisticated signaling mechanism.
#include <thread>
#include <atomic>
#include <chrono>
#include <iostream>
class S {
std::atomic<bool> running_;
std::thread thread_;
public:
S() : running_(true), thread_([this] () { work(); }) {}
void cancel() { running_ = false; }
~S() {
if ( running_ )
cancel();
if ( thread_.joinable() )
thread_.join();
}
private:
void work() {
while ( running_ ) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "tick ...\n";
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "... tock\n";
}
std::cout << "!running\n";
}
};
int main()
{
std::cout << "main()\n";
{
S s;
std::this_thread::sleep_for(std::chrono::milliseconds(2750));
std::cout << "end of main, should see a tock and then end\n";
}
std::cout << "finished\n";
}
Live demo: http://coliru.stacked-crooked.com/a/3b179f0f9f8bc2e1
I'm trying to get a class run a thread, which will call a virtual member function named Tick() in a loop. Then I tried to derive a class and override the base::Tick().
but when execute, the program just call the base class's Tick instead of override one. any solutions?
#include <iostream>
#include <atomic>
#include <thread>
#include <chrono>
using namespace std;
class Runnable {
public:
Runnable() : running_(ATOMIC_VAR_INIT(false)) {
}
~Runnable() {
if (running_)
thread_.join();
}
void Stop() {
if (std::atomic_exchange(&running_, false))
thread_.join();
}
void Start() {
if (!std::atomic_exchange(&running_, true)) {
thread_ = std::thread(&Runnable::Thread, this);
}
}
virtual void Tick() {
cout << "parent" << endl;
};
std::atomic<bool> running_;
private:
std::thread thread_;
static void Thread(Runnable *self) {
while(self->running_) {
self->Tick();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
};
class Fn : public Runnable {
public:
void Tick() {
cout << "children" << endl;
}
};
int main (int argc, char const* argv[])
{
Fn fn;
fn.Start();
return 0;
}
outputs:
parent
You can't let an object run out of scope until you're finished using it! The return 0; at the end of main causes fn to go out of scope. So by the time you get around to calling tick, there's no guarantee the object even exists any more.
(The logic in ~Runnable is totally broken. Inside the destructor is way too late -- the object is already at least partially destroyed.)
The approach of using inheritance with the parent serving as control for the thread and the children implementing the functions is a bad idea in general. The common problems with this approach come from construction and destruction:
if the thread is started from the constructor in the parent (control) then it might start running before the constructor completes and the thread might call the virtual function before the complete object has been fully constructed
if the thread is stopped in the destructor of the parent, then by the time that the control joins the thread, the thread is executing a method on an object that does no longer exist.
In your particular case you are hitting the second case. The program starts executing, and in main the second thread is started. At that point there is a race between the main thread and the newly launched, if the new thread is faster (unlikely, as starting the thread is an expensive operation), it will call the member method Tick that will be dispatched to the final overrider Fn::Tick.
But if the main thread is faster it will exit the scope of main, and it will start destruction of the object, it will complete destruction of the Fn object and during construction of the Runnable it will join the thread. If the main thread is fast enough, it will make it to the join before the second thread and wait there for the second thread to call Tick on the now final overrider that is Runnable::Tick. Note that this is Undefined Behavior, and not guaranteed, since the second thread is accessing an object that is being destroyed.
Also, there are other possible orderings, like for example, the second thread could dispatch to Fn::Tick before the main thread starts destruction, but might not complete the function before the main thread destroys the Fn sub object, in which case your second thread would be calling a member function on a dead object.
You should rather follow the approach in the C++ standard: separate the control from the logic, fully construct the object that will be run and pass it to the thread during construction. Note that this is the case of Java's Runnable, which is recommended over extending the Thread class. Note that from a design point of view this separation makes sense: the thread object manages the execution, and the runnable is the code to execute.
A thread is not a ticker, but rather what controls the execution of the ticker. And in your code Runnable is not something that can be run, but rather something that runs other objects that happen to derive from it.