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.