Split out low-level thread handling into SMXThread, and use it in SMXHelperThread.

This isn't used by the SMXManager thread for now.

This also separates out SMX::Event for thread event handling.
master
Glenn Maynard 6 years ago
parent a7cb6ad51d
commit d576545266
  1. 37
      sdk/Windows/Helpers.h
  2. 2
      sdk/Windows/SMX.vcxproj
  3. 6
      sdk/Windows/SMX.vcxproj.filters
  4. 51
      sdk/Windows/SMXHelperThread.cpp
  5. 22
      sdk/Windows/SMXHelperThread.h
  6. 49
      sdk/Windows/SMXThread.cpp
  7. 45
      sdk/Windows/SMXThread.h

@ -6,6 +6,7 @@
#include <windows.h>
#include <functional>
#include <memory>
#include <vector>
using namespace std;
namespace SMX
@ -99,6 +100,42 @@ public:
private:
Mutex &m_Mutex;
};
class Event
{
public:
Event(Mutex &lock):
m_Lock(lock)
{
m_hEvent = make_shared<AutoCloseHandle>(CreateEvent(NULL, false, false, NULL));
}
void Set()
{
SetEvent(m_hEvent->value());
}
// Unlock m_Lock, wait up to iDelayMilliseconds for the event to be set,
// then lock m_Lock. If iDelayMilliseconds is -1, wait forever.
void Wait(int iDelayMilliseconds)
{
if(iDelayMilliseconds == -1)
iDelayMilliseconds = INFINITE;
m_Lock.AssertLockedByCurrentThread();
m_Lock.Unlock();
vector<HANDLE> aHandles = { m_hEvent->value() };
WaitForSingleObjectEx(m_hEvent->value(), iDelayMilliseconds, true);
m_Lock.Lock();
}
private:
shared_ptr<SMX::AutoCloseHandle> m_hEvent;
Mutex &m_Lock;
};
}
#endif

@ -20,6 +20,7 @@
<ClInclude Include="SMXDeviceSearchThreaded.h" />
<ClInclude Include="SMXHelperThread.h" />
<ClInclude Include="SMXManager.h" />
<ClInclude Include="SMXThread.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Helpers.cpp" />
@ -30,6 +31,7 @@
<ClCompile Include="SMXDeviceSearchThreaded.cpp" />
<ClCompile Include="SMXHelperThread.cpp" />
<ClCompile Include="SMXManager.cpp" />
<ClCompile Include="SMXThread.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{C5FC0823-9896-4B7C-BFE1-B60DB671A462}</ProjectGuid>

@ -34,6 +34,9 @@
<ClInclude Include="SMXBuildVersion.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="SMXThread.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="SMX.cpp">
@ -60,5 +63,8 @@
<ClCompile Include="Helpers.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SMXThread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

@ -1,31 +1,10 @@
#include "SMXHelperThread.h"
#include <windows.h>
using namespace SMX;
SMX::SMXHelperThread::SMXHelperThread(const string &sThreadName)
{
m_hEvent = make_shared<AutoCloseHandle>(CreateEvent(NULL, false, false, NULL));
// Start the thread.
m_hThread = CreateThread(NULL, 0, ThreadMainStart, this, 0, &m_iThreadId);
SMX::SetThreadName(m_iThreadId, sThreadName);
}
SMX::SMXHelperThread::~SMXHelperThread()
{
}
void SMX::SMXHelperThread::SetHighPriority(bool bHighPriority)
{
SetThreadPriority( m_hThread, THREAD_PRIORITY_HIGHEST );
}
DWORD WINAPI SMX::SMXHelperThread::ThreadMainStart(void *self_)
SMX::SMXHelperThread::SMXHelperThread(const string &sThreadName):
SMXThread(m_Lock)
{
SMXHelperThread *self = (SMXHelperThread *) self_;
self->ThreadMain();
return 0;
Start(sThreadName);
}
void SMX::SMXHelperThread::ThreadMain()
@ -44,26 +23,13 @@ void SMX::SMXHelperThread::ThreadMain()
m_Lock.Unlock();
for(auto &func: funcs)
func();
WaitForSingleObjectEx(m_hEvent->value(), 250, true);
m_Lock.Lock();
m_Event.Wait(250);
}
m_Lock.Unlock();
}
void SMX::SMXHelperThread::Shutdown()
{
if(m_hThread == INVALID_HANDLE_VALUE)
return;
// Tell the thread to shut down, and wait for it before returning.
m_bShutdown = true;
SetEvent(m_hEvent->value());
WaitForSingleObject(m_hThread, INFINITE);
m_hThread = INVALID_HANDLE_VALUE;
}
void SMX::SMXHelperThread::RunInThread(function<void()> func)
{
m_Lock.AssertNotLockedByCurrentThread();
@ -71,11 +37,6 @@ void SMX::SMXHelperThread::RunInThread(function<void()> func)
// Add func to the list, and poke the event to wake up the thread if needed.
m_Lock.Lock();
m_FunctionsToCall.push_back(func);
SetEvent(m_hEvent->value());
m_Event.Set();
m_Lock.Unlock();
}
bool SMX::SMXHelperThread::IsCurrentThread() const
{
return GetCurrentThreadId() == m_iThreadId;
}

@ -2,6 +2,7 @@
#define SMXHelperThread_h
#include "Helpers.h"
#include "SMXThread.h"
#include <functional>
#include <vector>
@ -10,34 +11,19 @@ using namespace std;
namespace SMX
{
class SMXHelperThread
class SMXHelperThread: public SMXThread
{
public:
SMXHelperThread(const string &sThreadName);
~SMXHelperThread();
// Raise the priority of the helper thread.
void SetHighPriority(bool bHighPriority);
// Shut down the thread. Any calls queued by RunInThread will complete before
// this returns.
void Shutdown();
// Call func asynchronously from the helper thread.
void RunInThread(function<void()> func);
// Return true if this is the calling thread.
bool IsCurrentThread() const;
private:
static DWORD WINAPI ThreadMainStart(void *self_);
void ThreadMain();
DWORD m_iThreadId = 0;
// Helper threads use their independent lock.
SMX::Mutex m_Lock;
shared_ptr<SMX::AutoCloseHandle> m_hEvent;
bool m_bShutdown = false;
HANDLE m_hThread = INVALID_HANDLE_VALUE;
vector<function<void()>> m_FunctionsToCall;
};
}

@ -0,0 +1,49 @@
#include "SMXThread.h"
using namespace std;
using namespace SMX;
SMXThread::SMXThread(Mutex &lock):
m_Lock(lock),
m_Event(lock)
{
}
void SMX::SMXThread::SetHighPriority(bool bHighPriority)
{
if(m_hThread == INVALID_HANDLE_VALUE)
throw exception("SetHighPriority called while the thread isn't running");
SetThreadPriority(m_hThread, THREAD_PRIORITY_HIGHEST);
}
bool SMX::SMXThread::IsCurrentThread() const
{
return GetCurrentThreadId() == m_iThreadId;
}
void SMXThread::Start(string name)
{
// Start the thread.
m_hThread = CreateThread(NULL, 0, ThreadMainStart, this, 0, &m_iThreadId);
SMX::SetThreadName(m_iThreadId, name);
}
void SMXThread::Shutdown()
{
m_Lock.AssertNotLockedByCurrentThread();
// Shut down the thread and wait for it to exit.
m_bShutdown = true;
m_Event.Set();
WaitForSingleObject(m_hThread, INFINITE);
m_hThread = INVALID_HANDLE_VALUE;
}
DWORD WINAPI SMXThread::ThreadMainStart(void *self_)
{
SMXThread *self = (SMXThread *) self_;
self->ThreadMain();
return 0;
}

@ -0,0 +1,45 @@
#ifndef SMXThread_h
#define SMXThread_h
// A base class for a thread.
#include "Helpers.h"
#include <string>
namespace SMX
{
class SMXThread
{
public:
SMXThread(SMX::Mutex &lock);
// Raise the priority of the thread.
void SetHighPriority(bool bHighPriority);
// Start the thread, giving it a name for debugging.
void Start(std::string name);
// Shut down the thread. This function won't return until the thread
// has been stopped.
void Shutdown();
// Return true if this is the calling thread.
bool IsCurrentThread() const;
// The derived class implements this.
virtual void ThreadMain() = 0;
protected:
static DWORD WINAPI ThreadMainStart(void *self);
SMX::Mutex &m_Lock;
SMX::Event m_Event;
bool m_bShutdown = false;
private:
HANDLE m_hThread = INVALID_HANDLE_VALUE;
DWORD m_iThreadId = 0;
};
}
#endif
Loading…
Cancel
Save