#ifndef HEADER_ONLY_HELPER_CLASSES_DEFINED
#define HEADER_ONLY_HELPER_CLASSES_DEFINED
#include <string>
#include <process.h>
#include <time.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <Windows.h>
#undef GetObject
namespace Demo
{
// Critical section wrapper
class CS
{
public:
CS(): m_busy(false)
{
InitializeCriticalSection( &m_cs );
}
virtual ~CS()
{
DeleteCriticalSection( &m_cs );
}
bool IsBusy() const { return m_busy; } // Only valid at time of call
void Enter()
{
EnterCriticalSection( &m_cs );
m_busy = true;
}
void Leave()
{
// Be careful, linux allows other non-owner of cs to unlock
m_busy = false;
LeaveCriticalSection( &m_cs );
}
bool Try()
{
if (m_busy)
return false;
Enter();
return true;
}
private:
volatile bool m_busy;
CRITICAL_SECTION m_cs;
};
// Simple way to lock critical section (releases in destructor)
class CSLock
{
public:
CSLock(CS& cs)
{
m_localCs = &cs;
m_localCs->Enter();
}
virtual ~CSLock()
{
m_localCs->Leave();
}
private:
CS* m_localCs;
};
// Simple windows event wrapper
class Event
{
public:
Event()
{
m_event = CreateEvent(NULL, false, false, NULL);
}
virtual ~Event()
{
CloseHandle( m_event );
}
bool Wait(unsigned int timeout = INFINITE)
{
return WaitForSingleObject( m_event, timeout ) != WAIT_TIMEOUT;
}
bool Reset()
{
return ResetEvent( m_event ) != 0;
}
bool Signal()
{
return SetEvent( m_event ) != 0;
}
bool Try()
{
return Wait(0);
}
private:
HANDLE m_event;
};
// A thread class. Have your class derive from this one, override the Thread() function.
class Thread
{
bool Running;
bool ShuttingDown;
bool InUserThread;
HANDLE hThread;
unsigned int thrdaddr;
CS CS;
Event Event;
public:
Thread()
{
Running = false;
ShuttingDown = true;
InUserThread = false;
}
virtual ~Thread(){ ThreadStop(); }
virtual void ThreadAction() = 0; // Derive and override the ThreadAction function
bool ThreadActivate()
{
CSLock L(CS);
if (Running) return false;
ShuttingDown = false;
Running = true;
InUserThread = false;
hThread = (HANDLE) _beginthreadex(NULL, 0, CallBackThread ,(LPVOID) this, 0, &thrdaddr);
return true;
}
bool ThreadStart()
{
CSLock L(CS);
if (!Running || ShuttingDown || InUserThread) return false;
Event.Signal();
return true;
}
bool ThreadStop(unsigned long WaitTime = 1000)
{
{
CSLock L(CS);
if (!Running) return false;
ShuttingDown = true;
Event.Signal();
}
if (WaitForSingleObject(hThread, WaitTime) == WAIT_TIMEOUT)
TerminateThread(hThread,0);
Sleep(50);
thrdaddr = 0;
Running = false;
return true;
}
bool IsThreadRunning(){CSLock L(CS);return Running;};
bool IsThreadShuttingDown(){CSLock L(CS);return ShuttingDown;};
private:
static unsigned int __stdcall CallBackThread(void* p)
{
((Thread*)p)->InternalThread();
return 0;
}
void InternalThread()
{
while (!ShuttingDown)
{
if (Event.Wait(2000))
{
{
CSLock L(CS);
InUserThread = true;
}
ThreadAction();
{
CSLock L(CS);
InUserThread = false;
}
}
}
{
CSLock L(CS);
Running = false;
}
}
};
}// Namespace Demo
#endif