C++ destructor is crashing on function pointer - c++

I'm using Visual Studio 2017. I have a class defined thusly:
class Timer
{
friend class TimerFactory;
protected:
explicit Timer(std::function<void()>theCallback, uint theTimer, std::thread::id theThread, bool theImmediate, bool recurring) :
myCallback(theCallback), myTimer(theTimer), myThread(theThread), isImmediate(theImmediate), isRecurring(recurring), myWorkComplete(false)
{
}
Timer(const Timer& orig)
{
myCallback = orig.myCallback;
myTimer = orig.myTimer;
myThread = orig.myThread;
myWorkComplete = orig.myWorkComplete;
isImmediate = orig.isImmediate;
isRecurring = orig.isRecurring;
}
public:
~Timer()
{
}
void Start()
{
Run();
}
private:
std::function<void()>myCallback;
uint myTimer;
std::thread::id myThread;
bool myWorkComplete;
bool isImmediate;
bool isRecurring;
void Run();
};
void Timer::Run()
{
std::chrono::nanoseconds ms(myTimer);
begin: std::this_thread::sleep_for(ms);
if (!(myCallback == nullptr))
{
myCallback();
}
myWorkComplete = true;
if (isRecurring)
{
goto begin;
}
if (!isImmediate)
{
TimerFactory::GetInst()->TimerFired(myThread, this);
}
}
These guys are created like this:
std::function<void()> run_callback = std::bind(&Dispatcher::Run, this);
TimerFactory::GetInst()->CreateTimer(run_callback, MY_DISPATCHER_CLOCK_RATE, true, true);
And
void TimerFactory::CreateTimer(std::function<void()>theCallback, uint theInterval, bool theImmediate, bool recurring)
{
std::lock_guard<std::mutex> guard(myMutex);
if (myTerminated == true)
{
return;
}
thread* t = new thread(&TimerFactory::CreateTimerOnThread, theCallback, theInterval, theImmediate, recurring);
if (recurring)
{
t->detach();
}
else if (theImmediate)
{
t->join();
}
else
{
myThreads.push_back(t);
}
}
Followed by:
void TimerFactory::CreateTimerOnThread(std::function<void()>theCallback, uint theTimer, bool theImmediate, bool recurring)
{
if (theImmediate)
{
Timer p(theCallback, theTimer, std::this_thread::get_id(), theImmediate, recurring);
p.Start();
}
else
{
Timer* p = new (std::nothrow) Timer(theCallback, theTimer, std::this_thread::get_id(), theImmediate, recurring);
Dispatcher<Timer>::GetInst()->addElement(p);
}
}
The Timer objects that are !isImmediate are the ones that are causing the problem when I pop them off of a list:
template <typename T>
class Dispatcher
{
private:
static Dispatcher<T>* myInstance;
static std::once_flag myOnceFlag;
std::list<T*> myData;
std::mutex myMutex;
Dispatcher()
{
myInstance = this;
}
public:
static Dispatcher* GetInst()
{
std::call_once(Dispatcher::myOnceFlag, []() {new Dispatcher(); });
return Dispatcher::myInstance;
}
virtual void Initialize()
{
//std::lock_guard<std::mutex> guard(myMutex);
while (myData.size() > 0)
{
myData.pop_back();
}
std::function<void()> run_callback = std::bind(&Dispatcher::Run, this);
TimerFactory::GetInst()->CreateTimer(run_callback, MY_DISPATCHER_CLOCK_RATE, true, true);
}
/* Add an element to my list */
bool addElement(T* theElement)
{
std::lock_guard<std::mutex> guard(myMutex);
myData.push_back(theElement);
return true;
}
/* Clear my list */
void Reset()
{
std::lock_guard<std::mutex> guard(myMutex);
while (myData.size() > 0)
{
myData.pop_back();
T* temp = (*myData.begin());
myData.pop_front();
temp->Start();
delete temp; // This causes the exception.
}
}
virtual void Run()
{
std::lock_guard<std::mutex> guard(myMutex);
if (myData.size() > 0)
{
T* temp = (*myData.begin());
myData.pop_front();
temp->Start();
delete temp; // This is the line that leads to the exception.
}
}
};
I'm trying to wrap them in unique_ptrs but when the destructor gets called my application throws the exception:
Exception thrown at 0x0F695DCF (SudokuAPI.dll) in SudokuInterface.exe: 0xC0000005: Access violation reading location 0xDDDDDDDD. occurred
and the call stack is:
SudokuAPI.dll!std::_Func_class<void>::_Tidy() Line 470 C++ Symbols loaded.
SudokuAPI.dll!std::_Func_class<void>::~_Func_class<void>() Line 356 C++ Symbols loaded.
SudokuAPI.dll!std::function<void __cdecl(void)>::~function<void __cdecl(void)>() Line 53 C++ Symbols loaded.
SudokuAPI.dll!Timer::~Timer() Line 35 C++ Symbols loaded.
SudokuAPI.dll!Timer::`scalar deleting destructor'(unsigned int) C++ Non-user code. Symbols loaded.
This exception also occurs when not using unique_ptrs, so I'm stuck. Any thoughts would be greatly appreciated.

When a Timer starts with isRecurring = true, the thread it runs on never ends. Trying to destroy the Timer leads to undefined behaviour, as you have a running function where this is an invalid pointer

Related

C++ Timer with reset functionality

I want a Timer class with reset method. When the reset method is called, std::function<void(void)> func execution will be postponed for next interval milliseconds. Here is my code (obtained from C++ 11: Calling a C++ function periodically) (the reset method doesn't work correctly):
// .h
class Timer
{
public:
Timer(const int interval, const std::function<void(void)>& func);
~Timer();
void stop();
void start();
bool is_running() const noexcept;
void reset();
private:
const int interval_;
const std::function<void(void)> func_;
std::atomic<bool> execute_;
std::thread thd_;
};
//////////////////////////////////////////////////////////////////////////////////
// .cpp
utl::Timer::Timer(const int interval, const std::function<void(void)>& func) :
func_{ func },
interval_{ interval },
execute_(false)
{
}
utl::Timer::~Timer()
{
if (execute_.load(std::memory_order_acquire)) {
stop();
};
}
void utl::Timer::stop()
{
execute_.store(false, std::memory_order_release);
if (thd_.joinable())
thd_.join();
}
void utl::Timer::start()
{
if (execute_.load(std::memory_order_acquire)) {
stop();
};
execute_.store(true, std::memory_order_release);
thd_ = std::thread([this]()
{
while (execute_.load(std::memory_order_acquire)) {
func_();
std::this_thread::sleep_for(
std::chrono::milliseconds(interval_));
}
});
}
bool utl::Timer::is_running() const noexcept {
return (execute_.load(std::memory_order_acquire) &&
thd_.joinable());
}
void utl::Timer::reset()
{
stop();
start();
}
//////////////////////////////////////////////////////////////////////////////////
// a main function for test
#include <iostream>
using namespace std;
using namespace utl;
int main()
{
Timer timer(5000, []() {
cout << "reached!" << endl;
});
timer.start();
while (true)
{
cout << "working ...";
this_thread::sleep_for(std::chrono::seconds(1));
timer.reset();
}
}
This output of the main function (it is expected that string "reached!" not showed in cmd):
working ... reached! working ... reached! working
... reached! . . .
My problems are:
after calling start the func object is called without any delay.
reset method does not work

Cannot correctly stop thread pool

Here is my ThreadPool implementation. I've tried it in simple function main and cannot stop it correctly, destructor is called before threads start and whole program finish in the deadlock (on t.join()) because condition variable has been called before thread reached wait function.
Any ideas how to fix it? Or there is a better way to implement it?
ThreadPool.cpp
#include <condition_variable>
#include <future>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
namespace Concurrency {
template <typename RetType>
class StandardThreadPool : public ThreadPool<RetType> {
private:
typedef std::function<RetType()> taskType;
ThreadSafeQueue<std::packaged_task<RetType()>> queue;
std::mutex queueMutex;
std::condition_variable queueCondition;
std::vector<std::thread> poolThreads;
std::atomic<bool> stopThreadsFlag{false};
void threadWork() {
std::cout << "thread:" << std::this_thread::get_id() << " started\n";
std::unique_lock<std::mutex> lock(queueMutex);
while (true) {
queueCondition.wait(lock);
if (stopThreadsFlag.load())
break;
auto task = queue.Pop();
if (task)
(*task)();
}
std::cout << "thread:" << std::this_thread::get_id() << " finished\n";
}
void initThreadPool() {
poolThreads.resize(StandardThreadPool<RetType>::maxThreads);
}
void startThreads() {
for (int i = 0; i < StandardThreadPool<RetType>::maxThreads; i++) {
poolThreads[i] =
std::thread(&StandardThreadPool<RetType>::threadWork, this);
}
}
void terminateThreads() {
stopThreadsFlag.store(true);
queueCondition.notify_all();
for (auto &t : poolThreads) {
t.join();
}
}
public:
StandardThreadPool(int maxThreads) : ThreadPool<RetType>(maxThreads) {
initThreadPool();
startThreads();
}
std::future<RetType> virtual Push(taskType &&task) override {
std::packaged_task<RetType()> pt = std::packaged_task<RetType()>(task);
auto future = pt.get_future();
queue.Push(std::move(pt));
queueCondition.notify_one();
return future;
}
~StandardThreadPool<RetType>() {
std::cout << "destructor called\n";
terminateThreads(); }
};
} // namespace Concurrency
namespace Concurrency {
template <typename T> class ThreadSafeQueue {
private:
struct node {
std::shared_ptr<T> data;
std::unique_ptr<node> next;
};
std::mutex headMutex;
std::mutex tailMutex;
std::unique_ptr<node> head;
node *tail;
node *getTail() {
std::lock_guard<std::mutex> lock(tailMutex);
return tail;
}
std::unique_ptr<node> popHead() {
std::lock_guard<std::mutex> lock(headMutex);
if (head.get() == getTail())
return nullptr;
std::unique_ptr<node> oldHead(std::move(head));
head = std::move(oldHead->next);
return oldHead;
}
public:
ThreadSafeQueue() : head(new node), tail(head.get()) {}
std::shared_ptr<T> Pop() {
auto oldHead = popHead();
return oldHead ? oldHead->data : nullptr;
}
void Push(T &newValue) {
auto newData = std::make_shared<T>(std::forward<T>(newValue));
std::unique_ptr<node> pNew(new node);
auto newTail = pNew.get();
std::lock_guard<std::mutex> lock(tailMutex);
tail->data = newData;
tail->next = std::move(pNew);
tail = newTail;
}
void Push(T &&newValue) {
auto newData = std::make_shared<T>(std::move(newValue));
std::unique_ptr<node> pNew(new node);
auto newTail = pNew.get();
std::lock_guard<std::mutex> lock(tailMutex);
tail->data = newData;
tail->next = std::move(pNew);
tail = newTail;
}
ThreadSafeQueue(const ThreadSafeQueue &) = delete;
ThreadSafeQueue &operator=(const ThreadSafeQueue &) = delete;
};
} // namespace Concurrency
#include <functional>
#include <future>
namespace Concurrency {
template <typename RetType> class ThreadPool {
public:
int maxThreads;
public:
typedef std::function<RetType()> taskType;
ThreadPool(int maxThreads):maxThreads(maxThreads){}
virtual std::future<RetType> Push(taskType &&newTask) = 0;
ThreadPool(const ThreadPool &) = delete;
ThreadPool(const ThreadPool &&) = delete;
};
} // namespace Concurrency
main.cpp
int main() {
Concurrency::StandardThreadPool<int> th(1);
auto fun = []() {
std::cout << "function running\n";
return 2;
};
th.Push(fun);
return EXIT_SUCCESS;
}
First, a correct threadsafe queue.
template<class T>
struct threadsafe_queue {
[[nodiscard]] std::optional<T> pop() {
auto l = lock();
cv.wait(l, [&]{ return is_aborted() || !data.empty(); });
if (is_aborted())
return {};
auto r = std::move(data.front());
data.pop_front();
cv.notify_all(); // for wait_until_empty
return r; // might need std::move here, depending on compiler version
}
bool push(T t) {
auto l = lock();
if (is_aborted()) return false;
data.push_back(std::move(t));
cv.notify_one();
return true;
}
void set_abort_flag() {
auto l = lock(); // still need this
aborted = true;
data.clear();
cv.notify_all();
}
[[nodiscard]] bool is_aborted() const { return aborted; }
void wait_until_empty() {
auto l = lock();
cv.wait(l, [&]{ return data.empty(); });
}
private:
std::unique_lock<std::mutex> lock() {
return std::unique_lock<std::mutex>(m);
}
std::condition_variable cv;
std::mutex m;
std::atomic<bool> aborted{false};
std::deque<T> data;
};
this handles abort and the like internally.
Our threadpool then becomes:
struct threadpool {
explicit threadpool(std::size_t count)
{
for (std::size_t i = 0; i < count; ++i) {
threads.emplace_back([&]{
// abort handled by empty pop:
while( auto f = queue.pop() ) {
(*f)();
}
});
}
}
void set_abort_flag() {
queue.set_abort_flag();
}
[[nodiscard]] bool is_aborted() const {
return queue.is_aborted();
}
~threadpool() {
queue.wait_until_empty();
queue.set_abort_flag(); // get threads to leave the queue
for (std::thread& t:threads)
t.join();
}
template<class F,
class R=typename std::result_of<F()>::type
>
std::future<R> push_task( F f ) {
std::packaged_task<R()> task( std::move(f) );
auto ret = task.get_future();
if (queue.push( std::packaged_task<void()>(std::move(task)) )) // wait, this works? Yes it does.
return ret;
else
return {}; // cannot push, already aborted
}
private:
// yes, void. This is evil but it works
threadsafe_queue<std::packaged_task<void()>> queue;
std::vector<std::thread> threads;
};
in c++11 you can swap the std::optional for std::unique_ptr. More runtime overhead.
The trick here is that a std::packaged_task<void()> can store a std::packaged_task<R()>. And we don't need the return value in the queue. So one thread pool can handle any number of different return values in tasks -- it doesn't care.
I only join the threads on thread_pool destruction. I could do it after an abort as well.
Destroying a thread_pool waits until all tasks are complete. Note that aborting a thread_pool may not abort tasks in progress. One thing that you probably want to add is the option of passing an abort API/flag to the tasks, so they can abort early if asked.
Getting this industrial scale is hard, because ideally all blocking in a task would also pay attention to the abort possibility.
Live example.
You could add a 2nd cv to notify after pops, which only wait_until_empty waits on. That might safe you some spurious wakeups.

Segmentation fault when trying to clean object in Gtest

So, this is my test. But it has segmentation fault on the last line: m->service-> clean. And if I don't use this function, I have memory leaks. Is there any alternative?
class ServiceTest: public ::testing::Test
{
protected:
virtual void SetUp()
{
m_service = new conn::tsm::Service();
}
virtual void TearDown()
{
delete m_service;
m_service = 0;
}
// Tested Object:
conn::Service *m_service;
};
TEST_F(ServiceTest, CatchChildDelete)
{
conn::IObject_mock *testParam = new conn::IObject_mock();
m_service->setId(0x01);
EXPECT_CALL(*testParam, getId()).WillRepeatedly(::testing::Return(0x01));
EXPECT_TRUE(m_service->addObject(testParam));
EXPECT_CALL(*testParam, die()).WillOnce(::testing::Throw(std::exception()));
m_service->clean();
}
And this is the implementation of clean():
void Service::clean() throw()
{
try
{
std::vector<IObject *>::iterator it = m_objectTable.end();
for( it = m_objectTable.begin(); it != m_objectTable.end();++it )
{
delete (*it);
}
/* clear cache */
m_objectMap.clear();
m_objectTable.clear();
}
catch(...)
{
}
}

Proper usage of std::move

The following code works:
class Handler {
public:
Application* application;
bool handle(sf::Event&);
};
class TestApp {
public:
TestApp();
bool running;
void run();
void attach_handler(Handler*);
std::forward_list<std::unique_ptr<Handler>> handlerFList;
};
TestApp::TestApp() {
}
void Application::run() {
while (running) {
sf::Event event;
while (window->pollEvent(event)) {
for (auto& handler : handlerFList) {
if (handler->handle(event)) {
break;
}
}
}
}
}
void Application::attach_handler(Handler* handler) {
handlerFList.push_front(std::unique_ptr<Handler>(std::move(handler)));
handler->application = this;
}
int main() {
sqt::TestApp app;
sqe::HandlerClose hc;
app.attach_handler(&hc);
app.run();
return 0;
}
But this one does not:
class Handler {
public:
Application* application;
bool handle(sf::Event&);
};
class TestApp {
public:
TestApp();
bool running;
void run();
void attach_handler(Handler*);
std::forward_list<std::unique_ptr<Handler>> handlerFList;
};
TestApp::TestApp() {
sqe::HandlerClose hc;
attach_handler(&hc);
}
void TestApp::run() {
while (running) {
sf::Event event;
while (window->pollEvent(event)) {
for (auto& handler : handlerFList) {
if (handler->handle(event)) { // SEGFAULTS
break;
}
}
}
}
}
void TestApp::attach_handler(Handler* handler) {
handlerFList.push_front(std::unique_ptr<Handler>(std::move(handler)));
handler->application = this;
}
int main() {
sqt::TestApp app;
app.run();
return 0;
}
It segfaults where marked. I can't work out what I'm doing wrong. Isn't std::move supposed to move the base object? What it seems like is happening is that once TestApp's constructor finishes, the object is getting deleted. How can I fix this?

Making a timer that executes a function after a certain amount of time in milliseconds

Let's say I have this function:
void changeMap(Player* player, int map) {
player->setMap(map);
}
And I want a timer class that enables me to run that function after a certain amount of time, Something like this.
Player* chr;
int mapid = 300;
int milliseconds = 6000;
Timer.Schedule(changeMap(chr, 300), milliseconds);
Thanks in advance.
If this is a game loop then one way is to keep of list of events that you want to happen some time in the future where you store a time and a pointer to the function you want to call. (Or a std::function, or whatever). Keep the list sorted by time so the soonest event is a the top of the list.
Then in your main game loop, every loop, check the top of the list to see if the time of that event has been reached yet and if it has pop the event and call the function.
You can achieve the desired effect by the liberal use of Functor delegate objects and templates:
CAlarm.h
#ifndef CALARM_H
#define CALARM_H
#include "ADTtime.h"
#include "CStopwatch.h"
template<class FunctionObject>
class Alarm : public StopWatch {
public:
Alarm(const FunctionObject& fn);
Alarm(double tickTime, const FunctionObject& fn);
virtual ~Alarm();
FunctionObject Tick();
protected:
FunctionObject _delegate;
double _tickTime;
private:
};
template<class FunctionObject>
Alarm<FunctionObject>::Alarm(const FunctionObject& fn)
: StopWatch(), _delegate(fn), _tickTime(1.0) { }
template<class FunctionObject>
Alarm<FunctionObject>::Alarm(double tickTime, const FunctionObject& fn)
: StopWatch(), _delegate(fn), _tickTime(tickTime) { }
template<class FunctionObject>
Alarm<FunctionObject>::~Alarm() {
if(_isRunning) Stop();
}
template<class FunctionObject>
FunctionObject Alarm<FunctionObject>::Tick() {
if(IsRunning() == false) return _delegate;
if(GetElapsedTimeInSeconds() >= _tickTime) {
Reset();
_delegate();
}
return _delegate;
}
#endif
CStopwatch.h
#ifndef CSTOPWATCH_H
#define CSTOPWATCH_H
#include "ADTtime.h"
class StopWatch : public ADTTime {
public:
StopWatch();
virtual ~StopWatch();
void Start();
void Restart();
void Stop();
void Reset();
virtual void CalculateElapsedTime();
virtual double GetElapsedTimeInSeconds();
virtual double GetElapsedTimeInMilliseconds();
protected:
private:
};
#endif
CStopwatch.cpp
#include "CStopwatch.h"
StopWatch::StopWatch() : ADTTime() {
/* DO NOTHING. ALL INITIALIZATION HAPPENS IN BASE CLASS */
}
StopWatch::~StopWatch() {
_startTime = -1;
_endTime = -1;
_deltaTime = -1.0;
_isRunning = false;
}
void StopWatch::Start() {
if(_isRunning == true) return;
_startTime = clock();
_isRunning = true;
}
void StopWatch::Stop() {
if(_isRunning == false) return;
_isRunning = false;
CalculateElapsedTime();
}
void StopWatch::Restart() {
Reset();
Start();
}
void StopWatch::Reset() {
Stop();
_startTime = 0;
_endTime = 0;
_deltaTime = 0.0;
}
void StopWatch::CalculateElapsedTime() {
_endTime = clock();
_deltaTime = difftime(_startTime, _endTime);
}
double StopWatch::GetElapsedTimeInSeconds() {
CalculateElapsedTime();
return -ADTTime::GetElapsedTimeInSeconds();
}
double StopWatch::GetElapsedTimeInMilliseconds() {
CalculateElapsedTime();
return -ADTTime::GetElapsedTimeInMilliseconds();
}
ADTTime.h
#ifndef ADTTIME_H
#define ADTTIME_H
#include <ctime>
class ADTTime {
public:
clock_t GetStartTime() const;
clock_t GetStartTime();
double GetStartTimeInSeconds() const;
double GetStartTimeInSeconds();
clock_t GetEndTime() const;
clock_t GetEndTime();
double GetEndTimeInSeconds() const;
double GetEndTimeInSeconds();
virtual double GetElapsedTimeInSeconds();
virtual double GetElapsedTimeInMilliseconds();
virtual void CalculateElapsedTime()=0;
bool IsRunning() const;
bool IsRunning();
virtual void Start()=0;
virtual void Restart()=0;
virtual void Stop()=0;
virtual void Reset()=0;
ADTTime();
virtual ~ADTTime();
protected:
bool _isRunning;
clock_t _startTime;
clock_t _endTime;
double _deltaTime;
private:
};
#endif
CADTTime.cpp
#include "ADTtime.h"
clock_t ADTTime::GetStartTime() const {
return _startTime;
}
clock_t ADTTime::GetStartTime() {
return static_cast<const ADTTime&>(*this).GetStartTime();
}
double ADTTime::GetStartTimeInSeconds() const {
return static_cast<double>((_startTime / CLOCKS_PER_SEC));
}
double ADTTime::GetStartTimeInSeconds() {
return static_cast<const ADTTime&>(*this).GetStartTimeInSeconds();
}
clock_t ADTTime::GetEndTime() const {
return _endTime;
}
clock_t ADTTime::GetEndTime() {
return static_cast<const ADTTime&>(*this).GetEndTime();
}
double ADTTime::GetEndTimeInSeconds() const {
return static_cast<double>((_endTime / CLOCKS_PER_SEC));
}
double ADTTime::GetEndTimeInSeconds() {
return static_cast<const ADTTime&>(*this).GetEndTimeInSeconds();
}
double ADTTime::GetElapsedTimeInSeconds() {
return _deltaTime / CLOCKS_PER_SEC;
}
double ADTTime::GetElapsedTimeInMilliseconds() {
return _deltaTime;
}
bool ADTTime::IsRunning() const {
return _isRunning;
}
bool ADTTime::IsRunning() {
return static_cast<const ADTTime&>(*this).IsRunning();
}
ADTTime::ADTTime() : _isRunning(false), _startTime(-1), _endTime(-1), _deltaTime(-1.0) { }
ADTTime::~ADTTime() {
_isRunning = false;
_startTime = -1;
_endTime = -1;
_deltaTime = -1.0;
}
Since you are running on Windows OS, I don't understand why are you reinventing the wheel?
CComPtr<IReferenceClock> pReferenceClock;
HRESULT hr = CoCreateInstance( CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, IID_IReferenceClock, (void**)&pReferenceClock );
hr = pReferenceClock->AdviseTime( ... );
// or, hr = pReferenceClock->AdvisePeriodic( ... );
and once you are done,
hr = pReferenceClock->Unadvise( adviseCookie );
You can implement a simple (perhaps a bit rough around the edges) function that fire off a one-off event, like a timer, after a specified amount of milliseconds, using std::thread and std::chrono facilities
Something like that:
void doAfter( const std::function<void(void)>& f,
size_t intervalMs )
{
std::thread t{[f, intervalMs] () -> void
{
auto chronoInterval = std::chrono::milliseconds( intervalMs );
std::this_thread::sleep_for( chronoInterval );
f();
}
};
// You can either `t.detach()` the thread, or wait to `join` it in main
}