Switched to variadic impl for taskthread
This commit is contained in:
parent
9b145bf269
commit
84ed5cd1d5
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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">
|
||||
|
|
Loading…
Reference in New Issue