1
0
Fork 0

Switched to variadic impl for taskthread

This commit is contained in:
justin 2016-07-05 20:52:36 -06:00
parent 9b145bf269
commit 84ed5cd1d5
8 changed files with 179 additions and 127 deletions

View File

@ -4,6 +4,7 @@
*/
#include "console.h"
#include "taskthread.h"
/**
\brief Print a line with text, terminated with a newline to the console.
@ -31,6 +32,16 @@ void dprintf(const char* Format, ...)
va_end(args);
}
void GuiAddLogMessageAsync(const char* msg)
{
static StringConcatTaskThread_<void (*)(const std::string &)> task([](const std::string & msg)
{
GuiAddLogMessage(msg.c_str());
});
task.WakeUp(msg);
}
/**
\brief Print a formatted string to the console.
\param format The printf format to use (see documentation of printf for more information).
@ -41,5 +52,5 @@ void dprintf_args(const char* Format, va_list Args)
char buffer[16384];
vsnprintf_s(buffer, _TRUNCATE, Format, Args);
GuiAddLogMessage(buffer);
GuiAddLogMessageAsync(buffer);
}

View File

@ -261,20 +261,20 @@ duint dbggetdbgevents()
}
DWORD WINAPI updateCallStackThread(void* ptr)
static DWORD WINAPI updateCallStackThread(duint ptr)
{
stackupdatecallstack(duint(ptr));
stackupdatecallstack(ptr);
GuiUpdateCallStack();
return 0;
}
void updateCallStackAsync(duint ptr)
{
static TaskThread updateCallStackTask(updateCallStackThread);
static TaskThread_<decltype(&updateCallStackThread), duint> updateCallStackTask(&updateCallStackThread);
updateCallStackTask.WakeUp(ptr);
}
DWORD WINAPI updateSEHChainThread(void* ptr)
DWORD WINAPI updateSEHChainThread()
{
GuiUpdateSEHChain();
stackupdateseh();
@ -284,7 +284,7 @@ DWORD WINAPI updateSEHChainThread(void* ptr)
void updateSEHChainAsync()
{
static TaskThread updateSEHChainTask(updateSEHChainThread);
static auto updateSEHChainTask = MakeTaskThread(&updateSEHChainThread);
updateSEHChainTask.WakeUp();
}
@ -339,12 +339,8 @@ static DWORD WINAPI _debugUpdateGuiNoStack(void* disasm_addr)
void DebugUpdateGuiAsync(duint disasm_addr, bool stack)
{
static TaskThread DebugUpdateGuiStackTask(_debugUpdateGuiStack);
static TaskThread DebugUpdateGuiNoStackTask(_debugUpdateGuiNoStack);
if(stack)
DebugUpdateGuiStackTask.WakeUp(disasm_addr);
else
DebugUpdateGuiNoStackTask.WakeUp(disasm_addr);
static TaskThread_<decltype(&DebugUpdateGui), duint, bool> DebugUpdateGuiAsync(&DebugUpdateGui);
DebugUpdateGuiAsync.WakeUp(disasm_addr, stack);
}
void DebugUpdateStack(duint dumpAddr, duint csp, bool forceDump)
@ -484,16 +480,12 @@ static bool getConditionValue(const char* expression)
return true;
}
static DWORD WINAPI _guiSetDebugState(void* state)
{
GuiSetDebugState((DBGSTATE)(int)state);
return 0;
}
void GuiSetDebugStateAsync(DBGSTATE state)
{
static TaskThread GuiSetDebugStateTask(_guiSetDebugState);
static TaskThread_<decltype(&GuiSetDebugState), DBGSTATE> GuiSetDebugStateTask(&GuiSetDebugState);
GuiSetDebugStateTask.WakeUp(state);
}
void cbPauseBreakpoint()
{
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);

View File

@ -131,7 +131,7 @@ CMDRESULT cbDebugRun(int argc, char* argv[])
return STATUS_ERROR;
dbgsetispausedbyuser(false);
GuiSetDebugState(running);
GuiSetDebugStateAsync(running);
unlock(WAITID_RUN);
PLUG_CB_RESUMEDEBUG callbackInfo;
callbackInfo.reserved = 0;

View File

@ -244,7 +244,7 @@ void MemUpdateMap()
}
}
static DWORD WINAPI memUpdateMap(void* ptr)
static DWORD WINAPI memUpdateMap()
{
if(DbgIsDebugging())
{
@ -256,7 +256,7 @@ static DWORD WINAPI memUpdateMap(void* ptr)
void MemUpdateMapAsync()
{
static TaskThread MemUpdateMapTask(memUpdateMap, 1000);
static auto MemUpdateMapTask = MakeTaskThread(memUpdateMap, 1000);
MemUpdateMapTask.WakeUp();
}

View File

@ -1,88 +0,0 @@
#include "taskthread.h"
#include <thread>
struct TaskThreadDetails
{
HANDLE threadHandle;
bool active = true;
void* arg = 0;
TaskThread::TaskFunction_t fn;
CRITICAL_SECTION access;
HANDLE wakeup;
size_t minSleepTimeMs;
size_t wakeups = 0;
size_t execs = 0;
TaskThreadDetails()
{
wakeup = CreateSemaphore(0, 0, 1, 0);
InitializeCriticalSection(&access);
}
~TaskThreadDetails()
{
EnterCriticalSection(&access);
active = false;
LeaveCriticalSection(&access);
ReleaseSemaphore(wakeup, 1, 0);
WaitForSingleObject(threadHandle, INFINITE);
CloseHandle(threadHandle);
DeleteCriticalSection(&access);
CloseHandle(wakeup);
}
void WakeUp(void* _arg)
{
wakeups++;
EnterCriticalSection(&access);
arg = _arg;
LeaveCriticalSection(&access);
// This will fail if it's redundant, which is what we want.
ReleaseSemaphore(wakeup, 1, 0);
}
void Loop()
{
void* argLatch = 0;
while(active)
{
WaitForSingleObject(wakeup, INFINITE);
EnterCriticalSection(&access);
argLatch = arg;
LeaveCriticalSection(&access);
if(active)
{
fn(argLatch);
std::this_thread::sleep_for(std::chrono::milliseconds(minSleepTimeMs));
execs++;
}
}
}
};
static DWORD WINAPI __task_loop(void* ptr)
{
((TaskThreadDetails*)ptr)->Loop();
return 0;
}
void TaskThread::WakeUp(void* arg)
{
details->WakeUp(arg);
}
TaskThread::TaskThread(TaskFunction_t fn,
size_t minSleepTimeMs,
_SECURITY_ATTRIBUTES* lpThreadAttributes,
SIZE_T dwStackSize)
{
details = new TaskThreadDetails();
details->fn = fn;
details->minSleepTimeMs = minSleepTimeMs;
details->threadHandle = CreateThread(lpThreadAttributes, dwStackSize, __task_loop, details, 0, 0);
}
TaskThread::~TaskThread()
{
delete details;
details = 0;
}

View File

@ -1,23 +1,164 @@
#ifndef _TASKTHREAD_H
#define _TASKTHREAD_H
#include "_global.h"
struct _SECURITY_ATTRIBUTES;
#include <thread>
struct TaskThreadDetails;
#include <cstddef>
#include <tuple>
#include <type_traits>
#include <utility>
class TaskThread
const size_t TASK_THREAD_DEFAULT_SLEEP_TIME = 100;
template <typename F, typename... Args>
class TaskThread_
{
TaskThreadDetails* details = 0;
protected:
F fn;
std::tuple<Args...> args;
bool active = true;
std::thread thread;
CRITICAL_SECTION access;
HANDLE wakeupSemaphore;
size_t minSleepTimeMs = 0;
size_t wakeups = 0;
size_t execs = 0;
void Loop();
// Given new args, compress it into old args.
virtual std::tuple<Args...> CompressArguments(Args && ... args);
// Reset called after we latch in a value
virtual void ResetArgs() { }
public:
typedef DWORD(WINAPI* TaskFunction_t)(void*);
void WakeUp(void* arg = 0);
template <typename T> void WakeUp(T arg = 0) { WakeUp((void*)arg); }
TaskThread(TaskFunction_t,
size_t minSleepTimeMs = 50,
_SECURITY_ATTRIBUTES* lpThreadAttributes = 0,
SIZE_T dwStackSize = 0);
~TaskThread();
void WakeUp(Args...);
TaskThread_(F, size_t minSleepTimeMs = TASK_THREAD_DEFAULT_SLEEP_TIME);
~TaskThread_();
};
template <typename F>
class StringConcatTaskThread_ : public TaskThread_<F, std::string>
{
virtual std::tuple<std::string> CompressArguments(std::string && msg) override
{
std::get<0>(args) += msg;
return args;
}
// Reset called after we latch in a value
virtual void ResetArgs()
{
std::get<0>(args).resize(0);
}
public:
StringConcatTaskThread_(F fn, size_t minSleepTimeMs = TASK_THREAD_DEFAULT_SLEEP_TIME) : TaskThread_(fn, minSleepTimeMs) {}
};
template <typename F>
static inline TaskThread_<F> MakeTaskThread(F f, size_t minSleepTimeMs = TASK_THREAD_DEFAULT_SLEEP_TIME)
{
return TaskThread_<F>(f, minSleepTimeMs);
}
typedef TaskThread_<LPTHREAD_START_ROUTINE, void*> TaskThread;
// using aliases for cleaner syntax
template<class T> using Invoke = typename T::type;
template<unsigned...> struct seq { using type = seq; };
template<class S1, class S2> struct concat;
template<unsigned... I1, unsigned... I2>
struct concat<seq<I1...>, seq<I2...>>
: seq < I1..., (sizeof...(I1) + I2)... > {};
template<class S1, class S2> using Concat = Invoke<concat<S1, S2>>;
template<unsigned N> struct gen_seq;
template<unsigned N> using GenSeq = Invoke<gen_seq<N>>;
template<unsigned N>
struct gen_seq : Concat < GenSeq < N / 2 >, GenSeq < N - N / 2 >> {};
template<> struct gen_seq<0> : seq<> {};
template<> struct gen_seq<1> : seq<0> {};
#define DECLTYPE_AND_RETURN( eval ) -> decltype ( eval ) { return eval; }
template<typename F, typename Tuple, size_t ...S>
auto apply_tuple_impl(F && fn, Tuple && t, const seq<S...> &)
DECLTYPE_AND_RETURN(std::forward<F>(fn)(std::get<S>(std::forward<Tuple>(t))...));
template<typename F, typename Tuple>
auto apply_from_tuple(F && fn, Tuple && t)
DECLTYPE_AND_RETURN(apply_tuple_impl(std::forward<F>(fn), std::forward<Tuple>(t),
GenSeq <
std::tuple_size<typename std::remove_reference<Tuple>::type>::value
> ()));
template <typename F, typename... Args>
std::tuple<Args...> TaskThread_<F, Args...>::CompressArguments(Args && ... _args)
{
return std::make_tuple<Args...>(std::forward<Args>(_args)...);
}
template <typename F, typename... Args> void TaskThread_<F, Args...>::WakeUp(Args... _args)
{
wakeups++;
EnterCriticalSection(&access);
args = CompressArguments(std::forward<Args>(_args)...);
LeaveCriticalSection(&access);
// This will fail silently if it's redundant, which is what we want.
ReleaseSemaphore(wakeupSemaphore, 1, 0);
}
template <typename F, typename... Args> void TaskThread_<F, Args...>::Loop()
{
std::tuple<Args...> argLatch;
while(active)
{
WaitForSingleObject(wakeupSemaphore, INFINITE);
EnterCriticalSection(&access);
argLatch = args;
ResetArgs();
LeaveCriticalSection(&access);
if(active)
{
apply_from_tuple(fn, argLatch);
std::this_thread::sleep_for(std::chrono::milliseconds(minSleepTimeMs));
execs++;
}
}
}
template <typename F, typename... Args>
TaskThread_<F, Args...>::TaskThread_(F fn,
size_t minSleepTimeMs) : fn(fn), minSleepTimeMs(minSleepTimeMs)
{
wakeupSemaphore = CreateSemaphore(0, 0, 1, 0);
InitializeCriticalSection(&access);
thread = std::thread([this]
{
Loop();
});
}
template <typename F, typename... Args>
TaskThread_<F, Args...>::~TaskThread_()
{
EnterCriticalSection(&access);
active = false;
LeaveCriticalSection(&access);
ReleaseSemaphore(wakeupSemaphore, 1, 0);
thread.join();
DeleteCriticalSection(&access);
CloseHandle(wakeupSemaphore);
}
#endif // _TASKTHREAD_H

View File

@ -74,7 +74,6 @@
<ClCompile Include="stringformat.cpp" />
<ClCompile Include="stringutils.cpp" />
<ClCompile Include="symbolinfo.cpp" />
<ClCompile Include="taskthread.cpp" />
<ClCompile Include="tcpconnections.cpp" />
<ClCompile Include="thread.cpp" />
<ClCompile Include="threading.cpp" />

View File

@ -335,9 +335,6 @@
<ClCompile Include="datainst_helper.cpp">
<Filter>Source Files\Utilities</Filter>
</ClCompile>
<ClCompile Include="taskthread.cpp">
<Filter>Source Files\Utilities</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="x64_dbg.h">