Merging Live++ 1.5.0

#rb none
#rnx

[CL 7277271 by Ben Marsh in Dev-Build branch]
This commit is contained in:
Ben Marsh
2019-07-11 12:59:10 -04:00
parent 092d431659
commit 1c6a3b0220
65 changed files with 2885 additions and 1051 deletions
@@ -0,0 +1,231 @@
// Copyright 2011-2019 Molecular Matters GmbH, all rights reserved.
#include "LC_API.h"
#include "LC_ClientStartupThread.h"
#include "LC_CriticalSection.h"
#include "LC_SyncPoint.h"
#include "LC_Restart.h"
#include "LC_RunMode.h"
#include "LC_Logging.h"
#include "LPP_API.h"
namespace
{
// startup thread
static ClientStartupThread* g_startupThread = nullptr;
// critical section to ensure that startup thread is initialized only once
static CriticalSection g_ensureOneTimeStartup;
// default run mode
static RunMode::Enum g_runMode = RunMode::DEFAULT;
}
void api::Startup(ClientStartupThread* startupThread)
{
g_startupThread = startupThread;
restart::Startup();
}
void api::Shutdown(void)
{
restart::Shutdown();
g_startupThread = nullptr;
}
LPP_DLL_API(const char*) LppGetVersion(void)
{
return LPP_VERSION;
}
LPP_DLL_API(int) LppCheckVersion(const char* apiVersion)
{
if (strcmp(apiVersion, LPP_VERSION) == 0)
{
return 1;
}
LC_ERROR_USER("Version mismatch detected. API version: %s, DLL version: %s", LPP_VERSION, apiVersion);
return 0;
}
LPP_DLL_API(void) LppRegisterProcessGroup(const char* groupName)
{
// now that we have the process group name, start Live++.
// ensure that initialization can happen only once, even if the user calls this more than once.
{
CriticalSection::ScopedLock lock(&g_ensureOneTimeStartup);
static bool firstTime = true;
if (!firstTime)
{
// this was already called once, bail out
return;
}
firstTime = false;
}
g_startupThread->Start(groupName, g_runMode);
}
LPP_DLL_API(void) LppSyncPoint(void)
{
syncPoint::EnterTarget();
}
LPP_DLL_API(void) LppWaitForToken(void* token)
{
if (!token)
{
// nullptr tokens are returned by Live++ when trying to enable modules which are not loaded into the host process.
// therefore, we need to handle this case gracefully.
return;
}
g_startupThread->WaitForToken(token);
}
LPP_DLL_API(void) LppTriggerRecompile(void)
{
g_startupThread->TriggerRecompile();
}
LPP_DLL_API(void) LppLogMessage(const wchar_t* message)
{
g_startupThread->LogMessage(message);
}
LPP_DLL_API(void) LppBuildPatch(const wchar_t* moduleNames[], const wchar_t* objPaths[], const wchar_t* amalgamatedObjPaths[], unsigned int count)
{
g_startupThread->BuildPatch(moduleNames, objPaths, amalgamatedObjPaths, count);
}
LPP_DLL_API(void) LppInstallExceptionHandler(void)
{
g_startupThread->InstallExceptionHandler();
}
LPP_DLL_API(void) LppUseExternalBuildSystem(void)
{
g_runMode = RunMode::EXTERNAL_BUILD_SYSTEM;
}
LPP_DLL_API(int) LppWantsRestart(void)
{
return restart::WasRequested();
}
LPP_DLL_API(void) LppRestart(lpp::RestartBehaviour behaviour, unsigned int exitCode)
{
restart::Execute(behaviour, exitCode);
}
LPP_DLL_API(void*) LppEnableModule(const wchar_t* nameOfExeOrDll)
{
return g_startupThread->EnableModule(nameOfExeOrDll);
}
LPP_DLL_API(void*) LppEnableModules(const wchar_t* namesOfExeOrDll[], unsigned int count)
{
return g_startupThread->EnableModules(namesOfExeOrDll, count);
}
LPP_DLL_API(void*) LppEnableAllModules(const wchar_t* nameOfExeOrDll)
{
return g_startupThread->EnableAllModules(nameOfExeOrDll);
}
LPP_DLL_API(void*) LppDisableModule(const wchar_t* nameOfExeOrDll)
{
return g_startupThread->DisableModule(nameOfExeOrDll);
}
LPP_DLL_API(void*) LppDisableModules(const wchar_t* namesOfExeOrDll[], unsigned int count)
{
return g_startupThread->DisableModules(namesOfExeOrDll, count);
}
LPP_DLL_API(void*) LppDisableAllModules(const wchar_t* nameOfExeOrDll)
{
return g_startupThread->DisableAllModules(nameOfExeOrDll);
}
// BEGIN EPIC MOD - Adding ShowConsole command
LPP_DLL_API(void) LppShowConsole()
{
g_startupThread->ShowConsole();
}
// END EPIC MOD
// BEGIN EPIC MOD - Adding SetVisible command
LPP_DLL_API(void) LppSetVisible(bool visible)
{
g_startupThread->SetVisible(visible);
}
// END EPIC MOD
// BEGIN EPIC MOD - Adding SetActive command
LPP_DLL_API(void) LppSetActive(bool active)
{
g_startupThread->SetActive(active);
}
// END EPIC MOD
// BEGIN EPIC MOD - Adding SetBuildArguments command
LPP_DLL_API(void) LppSetBuildArguments(const wchar_t* arguments)
{
g_startupThread->SetBuildArguments(arguments);
}
// END EPIC MOD
// BEGIN EPIC MOD - Support for lazy-loading modules
LPP_DLL_API(void) LppEnableLazyLoadedModule(const wchar_t* nameOfExeOrDll)
{
HMODULE baseAddress = GetModuleHandle(nameOfExeOrDll);
g_startupThread->EnableLazyLoadedModule(nameOfExeOrDll, baseAddress);
}
// END EPIC MOD
LPP_DLL_API(void) LppApplySettingBool(const char* settingName, int value)
{
g_startupThread->ApplySettingBool(settingName, value);
}
LPP_DLL_API(void) LppApplySettingInt(const char* settingName, int value)
{
g_startupThread->ApplySettingInt(settingName, value);
}
LPP_DLL_API(void) LppApplySettingString(const char* settingName, const wchar_t* value)
{
g_startupThread->ApplySettingString(settingName, value);
}
@@ -0,0 +1,44 @@
// Copyright 2011-2019 Molecular Matters GmbH, all rights reserved.
#pragma once
#include "LPP_API.h"
class ClientStartupThread;
// internal API, initialized by entryPoint
namespace api
{
void Startup(ClientStartupThread* startupThread);
void Shutdown(void);
}
// external Live++ API exported into DLL
// BEGIN EPIC MOD - Internalizing API
#define LPP_DLL_API(_rv) _rv __cdecl
//#define LPP_DLL_API(_rv) extern "C" __declspec(dllexport) _rv __cdecl
// END EPIC MOD - Internalizing API
LPP_DLL_API(const char*) LppGetVersion(void);
LPP_DLL_API(int) LppCheckVersion(const char* apiVersion);
LPP_DLL_API(void) LppRegisterProcessGroup(const char* groupName);
LPP_DLL_API(void) LppSyncPoint(void);
LPP_DLL_API(void) LppWaitForToken(void* token);
LPP_DLL_API(void) LppTriggerRecompile(void);
LPP_DLL_API(void) LppLogMessage(const wchar_t* message);
LPP_DLL_API(void) LppBuildPatch(const wchar_t* moduleNames[], const wchar_t* objPaths[], const wchar_t* amalgamatedObjPaths[], unsigned int count);
LPP_DLL_API(void) LppInstallExceptionHandler(void);
LPP_DLL_API(void) LppUseExternalBuildSystem(void);
LPP_DLL_API(int) LppWantsRestart(void);
LPP_DLL_API(void) LppRestart(lpp::RestartBehaviour behaviour, unsigned int exitCode);
LPP_DLL_API(void*) LppEnableModule(const wchar_t* nameOfExeOrDll);
LPP_DLL_API(void*) LppEnableModules(const wchar_t* namesOfExeOrDll[], unsigned int count);
LPP_DLL_API(void*) LppEnableAllModules(const wchar_t* nameOfExeOrDll);
LPP_DLL_API(void*) LppDisableModule(const wchar_t* nameOfExeOrDll);
LPP_DLL_API(void*) LppDisableModules(const wchar_t* namesOfExeOrDll[], unsigned int count);
LPP_DLL_API(void*) LppDisableAllModules(const wchar_t* nameOfExeOrDll);
LPP_DLL_API(void) LppApplySettingBool(const char* settingName, int value);
LPP_DLL_API(void) LppApplySettingInt(const char* settingName, int value);
LPP_DLL_API(void) LppApplySettingString(const char* settingName, const wchar_t* value);
@@ -12,6 +12,8 @@
#include "LC_Event.h"
#include "LC_CriticalSection.h"
#include "LC_PrimitiveNames.h"
#include "LC_Environment.h"
#include "LC_MemoryStream.h"
#include "LC_Logging.h"
#include "Misc/Paths.h"
#include "Misc/ConfigCacheIni.h"
@@ -237,6 +239,18 @@ void ClientStartupThread::TriggerRecompile(void)
}
void ClientStartupThread::LogMessage(const wchar_t* message)
{
// wait for the startup thread to finish initialization
Join();
if (m_userCommandThread)
{
m_userCommandThread->LogMessage(message);
}
}
void ClientStartupThread::BuildPatch(const wchar_t* moduleNames[], const wchar_t* objPaths[], const wchar_t* amalgamatedObjPaths[], unsigned int count)
{
// wait for the startup thread to finish initialization
@@ -488,7 +502,48 @@ unsigned int ClientStartupThread::ThreadFunction(const std::wstring& processGrou
m_userCommandThread->Start(processGroupName, m_startEvent, m_pipeClientCS);
// register this process with Live++
m_pipeClient->SendCommandAndWaitForAck(commands::RegisterProcess { process::GetBase(), process::GetId(), commandThreadId, &JumpToSelf }, nullptr, 0u);
{
// try getting the previous process ID from the environment in case the process was restarted
unsigned int restartedProcessId = 0u;
const std::wstring& processIdStr = environment::GetVariable(L"LPP_PROCESS_RESTART_ID", nullptr);
if (processIdStr.length() != 0u)
{
restartedProcessId = static_cast<unsigned int>(std::stoi(processIdStr));
environment::RemoveVariable(L"LPP_PROCESS_RESTART_ID");
}
// store the current process ID in an environment variable.
// upon restart, the environment block is inherited by the new process and can be used to map the process IDs of
// restarted processes to their previous IDs.
{
const unsigned int processID = process::GetId();
environment::SetVariable(L"LPP_PROCESS_RESTART_ID", std::to_wstring(processID).c_str());
}
const std::wstring& imagePath = process::GetImagePath();
const std::wstring& commandLine = process::GetCommandLine();
const std::wstring& workingDirectory = process::GetWorkingDirectory();
process::Environment* environment = process::CreateEnvironment(::GetCurrentProcess());
const commands::RegisterProcess command =
{
process::GetBase(), process::GetId(), restartedProcessId, commandThreadId, &JumpToSelf,
(imagePath.size() + 1u) * sizeof(wchar_t),
(commandLine.size() + 1u) * sizeof(wchar_t),
(workingDirectory.size() + 1u) * sizeof(wchar_t),
environment->size
};
memoryStream::Writer payload(command.imagePathSize + command.commandLineSize + command.workingDirectorySize + command.environmentSize);
payload.Write(imagePath.data(), command.imagePathSize);
payload.Write(commandLine.data(), command.commandLineSize);
payload.Write(workingDirectory.data(), command.workingDirectorySize);
payload.Write(environment->data, environment->size);
m_pipeClient->SendCommandAndWaitForAck(command, payload.GetData(), payload.GetSize());
process::DestroyEnvironment(environment);
}
// handle commands until registration is finished
{
@@ -37,6 +37,7 @@ public:
void WaitForToken(void* token);
void TriggerRecompile(void);
void LogMessage(const wchar_t* message);
void BuildPatch(const wchar_t* moduleNames[], const wchar_t* objPaths[], const wchar_t* amalgamatedObjPaths[], unsigned int count);
void InstallExceptionHandler(void);
@@ -361,6 +361,18 @@ void ClientUserCommandThread::TriggerRecompile(void)
}
void ClientUserCommandThread::LogMessage(const wchar_t* message)
{
const size_t lengthWithoutNull = wcslen(message);
const size_t payloadSize = sizeof(wchar_t) * (lengthWithoutNull + 1u);
ProxyCommand<commands::LogMessage>* proxy = new ProxyCommand<commands::LogMessage>(false, payloadSize);
proxy->m_payload.Write(message, payloadSize);
PushUserCommand(proxy);
}
void ClientUserCommandThread::BuildPatch(const wchar_t* moduleNames[], const wchar_t* objPaths[], const wchar_t* amalgamatedObjPaths[], unsigned int count)
{
const size_t perFileSize = sizeof(wchar_t) * MAX_PATH * 3u;
@@ -60,6 +60,7 @@ public:
void WaitForToken(void* token);
void TriggerRecompile(void);
void LogMessage(const wchar_t* message);
void BuildPatch(const wchar_t* moduleNames[], const wchar_t* objPaths[], const wchar_t* amalgamatedObjPaths[], unsigned int count);
// BEGIN EPIC MOD - Adding ShowConsole command
@@ -55,6 +55,7 @@ CommandMap::CommandMap(void)
RegisterDefaultAction<commands::CompilationFinished>(m_actions);
RegisterDefaultAction<commands::DisconnectClient>(m_actions);
RegisterDefaultAction<commands::TriggerRecompile>(m_actions);
RegisterDefaultAction<commands::LogMessage>(m_actions);
RegisterDefaultAction<commands::BuildPatch>(m_actions);
RegisterDefaultAction<commands::HandleException>(m_actions);
RegisterDefaultAction<commands::HandleExceptionFinished>(m_actions);
@@ -37,9 +37,17 @@ namespace commands
static const uint32_t ID = Acknowledge::ID + 1u;
void* processBase;
unsigned int processId;
unsigned int threadId; // thread ID of Live++ thread running in host
const void* jumpToSelf; // address of jump-to-self instruction in host
unsigned int processId; // current process ID
unsigned int restartedProcessId; // process ID of the previous, restarted process. 0 if non-existent
unsigned int threadId; // thread ID of Live++ thread running in host
const void* jumpToSelf; // address of jump-to-self instruction in host
size_t imagePathSize;
size_t commandLineSize;
size_t workingDirectorySize;
size_t environmentSize;
// image path, command line, working directory and environment follow as payload
};
// tell the DLL that registration has finished
@@ -175,10 +183,16 @@ namespace commands
static const uint32_t ID = DisconnectClient::ID + 1u;
};
// tell Live++ to log a message
struct LogMessage
{
static const uint32_t ID = TriggerRecompile::ID + 1u;
};
// tell Live++ to build a patch using an array of object files
struct BuildPatch
{
static const uint32_t ID = TriggerRecompile::ID + 1u;
static const uint32_t ID = LogMessage::ID + 1u;
unsigned int fileCount;
@@ -2,20 +2,13 @@
#include "LC_EntryPoint.h"
#include "LC_ClientStartupThread.h"
#include "LC_CriticalSection.h"
#include "LC_RunMode.h"
#include "LPP_API.h"
#include "LC_API.h"
namespace
{
// startup thread. initialized when LppRegisterProcessGroup is called
// startup thread
static ClientStartupThread* g_startupThread = nullptr;
// critical section to ensure that startup thread is initialized only once
static CriticalSection g_ensureOneTimeStartup;
static RunMode::Enum g_runMode = RunMode::DEFAULT;
}
@@ -23,11 +16,14 @@ namespace
void Startup(HINSTANCE instance)
{
g_startupThread = new ClientStartupThread(instance);
api::Startup(g_startupThread);
}
void Shutdown(void)
{
api::Shutdown();
// wait for the startup thread to finish its work and clean up
g_startupThread->Join();
delete g_startupThread;
@@ -51,179 +47,6 @@ BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD dwReason, _In_ LPVOID /*
break;
}
return Windows::TRUE;
return TRUE;
}
#endif
// END EPIC MOD
// exported Live++ API
// BEGIN EPIC MOD - Internalizing API
#define LPP_DLL_API
//#define LPP_DLL_API extern "C" __declspec(dllexport)
// END EPIC MOD - Internalizing API
LPP_DLL_API void __cdecl LppRegisterProcessGroup(const char* groupName)
{
// now that we have the process group name, start Live++.
// ensure that initialization can happen only once, even if the user calls this more than once.
{
CriticalSection::ScopedLock lock(&g_ensureOneTimeStartup);
static bool firstTime = true;
if (!firstTime)
{
// this was already called once, bail out
return;
}
firstTime = false;
}
g_startupThread->Start(groupName, g_runMode);
}
LPP_DLL_API void* __cdecl LppEnableModule(const wchar_t* nameOfExeOrDll)
{
// hand command creation to the user command thread
return g_startupThread->EnableModule(nameOfExeOrDll);
}
LPP_DLL_API void* __cdecl LppEnableModules(const wchar_t* namesOfExeOrDll[], unsigned int count)
{
// hand command creation to the user command thread
return g_startupThread->EnableModules(namesOfExeOrDll, count);
}
LPP_DLL_API void* __cdecl LppEnableAllModules(const wchar_t* nameOfExeOrDll)
{
// hand command creation to the user command thread
return g_startupThread->EnableAllModules(nameOfExeOrDll);
}
LPP_DLL_API void* __cdecl LppDisableModule(const wchar_t* nameOfExeOrDll)
{
// hand command creation to the user command thread
return g_startupThread->DisableModule(nameOfExeOrDll);
}
LPP_DLL_API void* __cdecl LppDisableModules(const wchar_t* namesOfExeOrDll[], unsigned int count)
{
// hand command creation to the user command thread
return g_startupThread->DisableModules(namesOfExeOrDll, count);
}
LPP_DLL_API void* __cdecl LppDisableAllModules(const wchar_t* nameOfExeOrDll)
{
// hand command creation to the user command thread
return g_startupThread->DisableAllModules(nameOfExeOrDll);
}
LPP_DLL_API void __cdecl LppWaitForToken(void* token)
{
if (!token)
{
// nullptr tokens are returned by Live++ when trying to enable modules which are not loaded into the host process.
// therefore, we need to handle this case gracefully.
return;
}
g_startupThread->WaitForToken(token);
}
LPP_DLL_API void __cdecl LppTriggerRecompile(void)
{
g_startupThread->TriggerRecompile();
}
LPP_DLL_API void __cdecl LppBuildPatch(const wchar_t* moduleNames[], const wchar_t* objPaths[], const wchar_t* amalgamatedObjPaths[], unsigned int count)
{
g_startupThread->BuildPatch(moduleNames, objPaths, amalgamatedObjPaths, count);
}
LPP_DLL_API void __cdecl LppInstallExceptionHandler(void)
{
g_startupThread->InstallExceptionHandler();
}
LPP_DLL_API void __cdecl LppUseExternalBuildSystem(void)
{
g_runMode = RunMode::EXTERNAL_BUILD_SYSTEM;
}
// BEGIN EPIC MOD - Adding ShowConsole command
LPP_DLL_API void __cdecl LppShowConsole()
{
g_startupThread->ShowConsole();
}
// END EPIC MOD
// BEGIN EPIC MOD - Adding SetVisible command
LPP_DLL_API void __cdecl LppSetVisible(bool visible)
{
g_startupThread->SetVisible(visible);
}
// END EPIC MOD
// BEGIN EPIC MOD - Adding SetActive command
LPP_DLL_API void __cdecl LppSetActive(bool active)
{
g_startupThread->SetActive(active);
}
// END EPIC MOD
// BEGIN EPIC MOD - Adding SetBuildArguments command
LPP_DLL_API void __cdecl LppSetBuildArguments(const wchar_t* arguments)
{
g_startupThread->SetBuildArguments(arguments);
}
// END EPIC MOD
// BEGIN EPIC MOD - Support for lazy-loading modules
LPP_DLL_API void __cdecl LppEnableLazyLoadedModule(const wchar_t* nameOfExeOrDll)
{
HMODULE baseAddress = GetModuleHandle(nameOfExeOrDll);
g_startupThread->EnableLazyLoadedModule(nameOfExeOrDll, baseAddress);
}
// END EPIC MOD
LPP_DLL_API void __cdecl LppApplySettingBool(const char* settingName, int value)
{
// hand command creation to the user command thread
g_startupThread->ApplySettingBool(settingName, value);
}
LPP_DLL_API void __cdecl LppApplySettingInt(const char* settingName, int value)
{
// hand command creation to the user command thread
g_startupThread->ApplySettingInt(settingName, value);
}
LPP_DLL_API void __cdecl LppApplySettingString(const char* settingName, const wchar_t* value)
{
// hand command creation to the user command thread
g_startupThread->ApplySettingString(settingName, value);
}
#undef LPP_DLL_API
@@ -0,0 +1,54 @@
// Copyright 2011-2019 Molecular Matters GmbH, all rights reserved.
#include "LC_Environment.h"
#include "LC_Logging.h"
#include "Windows/WindowsHWrapper.h"
namespace
{
static const DWORD MAX_VARIABLE_SIZE = 1024u;
}
void environment::RemoveVariable(const wchar_t* variable)
{
const BOOL result = ::SetEnvironmentVariableW(variable, NULL);
if (result == 0)
{
LC_LOG_DEV("Could not remove environment variable %S (Error: %d)", variable, ::GetLastError());
}
}
void environment::SetVariable(const wchar_t* variable, const wchar_t* value)
{
const BOOL result = ::SetEnvironmentVariableW(variable, value);
if (result == 0)
{
LC_LOG_DEV("Could not set environment variable %S to value %S (Error: %d)", variable, value, ::GetLastError());
}
}
std::wstring environment::GetVariable(const wchar_t* variable, const wchar_t* defaultValue)
{
std::wstring value;
value.resize(MAX_VARIABLE_SIZE);
const DWORD result = ::GetEnvironmentVariableW(variable, &value[0], MAX_VARIABLE_SIZE);
if (result == 0)
{
// if a default value was provided, return that instead
if (defaultValue)
{
return std::wstring(defaultValue);
}
else
{
return std::wstring();
}
}
return value;
}
@@ -0,0 +1,18 @@
// Copyright 2011-2019 Molecular Matters GmbH, all rights reserved.
#pragma once
#include "CoreTypes.h"
#include <string>
namespace environment
{
// Removes a variable from the environment of the calling process.
void RemoveVariable(const wchar_t* variable);
// Sets a variable in the environment of the calling process.
void SetVariable(const wchar_t* variable, const wchar_t* value);
// Gets a variable from the environment of the calling process.
std::wstring GetVariable(const wchar_t* variable, const wchar_t* defaultValue);
}
@@ -26,43 +26,21 @@ Event::~Event(void)
}
void Event::Signal(void)
{
::SetEvent(m_event);
}
void Event::Reset(void)
{
::ResetEvent(m_event);
}
void Event::Wait(void)
void Event::Signal(void)
{
const DWORD result = ::WaitForSingleObject(m_event, INFINITE);
switch (result)
{
case WAIT_OBJECT_0:
// event was successfully signaled
break;
::SetEvent(m_event);
}
case WAIT_TIMEOUT:
// the operation timed out, which should never happen with a timeout of INFINITE
LC_ERROR_DEV("Event timed out.");
break;
case WAIT_ABANDONED:
LC_ERROR_DEV("Wait() was called on a stale event which was not released by the owning thread.");
break;
case WAIT_FAILED:
LC_ERROR_DEV("Failed to Wait() on an event.");
break;
default:
break;
}
bool Event::Wait(void)
{
return WaitTimeout(INFINITE);
}
@@ -72,9 +50,15 @@ bool Event::WaitTimeout(unsigned int milliSeconds)
switch (result)
{
case WAIT_OBJECT_0:
// event was successfully signaled
return true;
case WAIT_TIMEOUT:
// the operation timed out, which should never happen with a timeout of INFINITE
if (milliSeconds == INFINITE)
{
LC_ERROR_DEV("Event timed out.");
}
return false;
case WAIT_ABANDONED:
@@ -89,3 +73,9 @@ bool Event::WaitTimeout(unsigned int milliSeconds)
return false;
}
}
bool Event::TryWait(void)
{
return WaitTimeout(0u);
}
@@ -22,13 +22,22 @@ public:
Event(const wchar_t* name, Type::Enum type);
~Event(void);
void Signal(void);
// Resets the event.
void Reset(void);
void Wait(void);
// returns true if the event was signaled
// Signals the event.
void Signal(void);
// Waits until the event becomes signaled, blocking.
bool Wait(void);
// Waits until the event becomes signaled, blocking until the timeout is reached.
// Returns whether the event was signaled.
bool WaitTimeout(unsigned int milliSeconds);
// Returns whether the event was signaled, non-blocking.
bool TryWait(void);
private:
Windows::HANDLE m_event;
};
@@ -5,6 +5,7 @@
#include "LiveCodingLog.h"
#include <atomic>
namespace
{
// we want to be able to dump large things, including environment variable blocks, but 32k on the stack is too much
@@ -21,6 +21,12 @@ void memoryStream::Reader::Read(void* data, size_t size)
}
void memoryStream::Reader::Seek(size_t offset)
{
m_offset = offset;
}
memoryStream::Writer::Writer(size_t capacity)
: m_data(new char[capacity])
, m_capacity(capacity)
@@ -22,6 +22,8 @@ namespace memoryStream
return data;
}
void Seek(size_t offset);
private:
const void* m_data;
size_t m_capacity;
@@ -6,17 +6,24 @@
#include "Misc/AssertionMacros.h"
#include "LC_Preprocessor.h"
#define LC_FILE __FILE__
#define LC_LINE __LINE__
#define LC_FUNCTION_NAME __FUNCTION__
#define LC_FUNCTION_SIGNATURE __FUNCSIG__
#define LC_UNUSED(_value) (void)_value
#define LC_ASSERT(_condition, _msg) checkf(_condition, TEXT("%s"), TEXT(_msg))
#if DO_CHECK
# define LC_BREAKPOINT() ((::IsDebuggerPresent() == 0) ? (void)true : __debugbreak())
#else
# define LC_BREAKPOINT() (void)true
#endif
#define LC_DISABLE_COPY(_name) _name(const _name&) = delete
#define LC_DISABLE_MOVE(_name) _name(_name&&) = delete
#define LC_DISABLE_ASSIGNMENT(_name) _name& operator=(const _name&) = delete
#define LC_DISABLE_MOVE_ASSIGNMENT(_name) _name& operator=(_name&&) = delete
#define LC_ASSERT(_condition, _msg) checkf(_condition, TEXT("%s"), TEXT(_msg))
#define LC_FILE __FILE__
#define LC_LINE __LINE__
#define LC_FUNCTION_NAME __FUNCTION__
#define LC_FUNCTION_SIGNATURE __FUNCSIG__
#define LC_UNUSED(_value) (void)(_value)
#define LC_DISABLE_COPY(_name) _name(const _name&) = delete
#define LC_DISABLE_MOVE(_name) _name(_name&&) = delete
#define LC_DISABLE_ASSIGNMENT(_name) _name& operator=(const _name&) = delete
#define LC_DISABLE_MOVE_ASSIGNMENT(_name) _name& operator=(_name&&) = delete
#if PLATFORM_64BITS
# define LC_64_BIT 1
@@ -18,6 +18,14 @@ namespace pointer
}
template <typename To, typename From>
To FromInteger(From integer)
{
// widen integer to width of pointer type first before converting to pointer
return reinterpret_cast<To>(static_cast<uintptr_t>(integer));
}
template <typename T>
T AlignBottom(void* anyPointer, size_t alignment)
{
@@ -8,12 +8,16 @@
#define LPP_JOB LPP L"_JOB"
#define LPP_MUTEX LPP L"_IPM"
#define LPP_MEMORY LPP L"_NSM"
#define LPP_EVENT LPP L"_EVT"
#define LPP_SERVER_READY LPP L"_SR"
#define LPP_COMPILE LPP L"_CMP"
#define LPP_PIPE L"\\\\.\\pipe\\UE_LC"
#define LPP_EXCEPTION_PIPE L"\\\\.\\pipe\\UE_LC_EXC"
#define LPP_HEARTBEAT_MUTEX LPP_MUTEX L"_HB"
#define LPP_HEARTBEAT_MEMORY LPP_MEMORY L"_HB"
#define LPP_RESTART_REQUESTED LPP_EVENT L"_RST_REQ"
#define LPP_RESTART_PREPARED LPP_EVENT L"_RST_PREP"
#define LPP_RESTART LPP_EVENT L"_RST"
std::wstring primitiveNames::JobGroup(const std::wstring& processGroupName)
@@ -126,13 +130,53 @@ std::wstring primitiveNames::HeartBeatNamedSharedMemory(const std::wstring& proc
}
std::wstring primitiveNames::RequestRestart(unsigned int processId)
{
std::wstring name;
name.reserve(128u);
name += LPP_RESTART_REQUESTED;
name += std::to_wstring(processId);
return name;
}
std::wstring primitiveNames::PreparedRestart(unsigned int processId)
{
std::wstring name;
name.reserve(128u);
name += LPP_RESTART_PREPARED;
name += std::to_wstring(processId);
return name;
}
std::wstring primitiveNames::Restart(unsigned int processId)
{
std::wstring name;
name.reserve(128u);
name += LPP_RESTART;
name += std::to_wstring(processId);
return name;
}
#undef LPP
#undef LPP_JOB
#undef LPP_MUTEX
#undef LPP_MEMORY
#undef LPP_EVENT
#undef LPP_SERVER_READY
#undef LPP_COMPILE
#undef LPP_PIPE
#undef LPP_EXCEPTION_PIPE
#undef LPP_HEARTBEAT_MUTEX
#undef LPP_HEARTBEAT_MEMORY
#undef LPP_RESTART_REQUESTED
#undef LPP_RESTART_PREPARED
#undef LPP_RESTART
@@ -23,4 +23,9 @@ namespace primitiveNames
// heart beat
std::wstring HeartBeatMutex(const std::wstring& processGroupName, unsigned int processId);
std::wstring HeartBeatNamedSharedMemory(const std::wstring& processGroupName, unsigned int processId);
// restart
std::wstring RequestRestart(unsigned int processId);
std::wstring PreparedRestart(unsigned int processId);
std::wstring Restart(unsigned int processId);
}

Some files were not shown because too many files have changed in this diff Show More