Files
UnrealEngineUWP/Engine/Source/Developer/Windows/LiveCodingServer/Private/External/LC_Scheduler.cpp

159 lines
3.6 KiB
C++
Raw Normal View History

Integrating live coding feature (aka Live++) into UE4. Allows fast iteration of C++ changes without restarting the application. To use, select the "Live Coding (Experimental)" mode from the drop down menu next to the editor's compile button, or type "LiveCoding" into the console for a monolithic build. Press Ctrl+Alt+F11 to find changes and compile. Changes vs standalone Live++ version: * UBT is used to execute builds. This allows standard UE4 adaptive unity mode, allows us to reuse object files when we do regular builds, supports using any build executor allowed by UBT (XGE, SNDBS, etc..). * Adding new source files is supported. * Custom visualizer for FNames is supported via a weakly linked symbol in a static library (Engine/Extras/NatvisHelpers). * Settings are exposed in the editor's project settings dialog. * Standalone application has been rewritten as a Slate app ("LiveCodingConsole"). There is an additional option to start the program as hidden, where it will not be visible until Ctrl+Alt+F11 is hit. Similarly, closing the window will hide it instead of closing the application. * Does not require a standalone licensed version of Live++. Known issues: * Does not currently support class layout changes / object reinstancing #rb none [FYI] Marc.Audy, Stefan.Boberg, Nick.Penwarden #jira #ROBOMERGE-OWNER: ryan.vance #ROBOMERGE-AUTHOR: ben.marsh #ROBOMERGE-SOURCE: CL 5304722 in //UE4/Release-4.22/... via CL 5309051 #ROBOMERGE-BOT: DEVVR (Main -> Dev-VR) [CL 5329502 by ben marsh in Dev-VR branch]
2019-03-06 18:34:25 -05:00
// Copyright 2011-2019 Molecular Matters GmbH, all rights reserved.
#include "LC_Scheduler.h"
#include "LC_SchedulerWorkerThread.h"
#include "LC_SchedulerQueue.h"
#include "LC_Thread.h"
// BEGIN EPIC MODS
#pragma warning(push)
#pragma warning(disable:6011) // warning C6011: Dereferencing NULL pointer 'info'.
// END EPIC MODS
Integrating live coding feature (aka Live++) into UE4. Allows fast iteration of C++ changes without restarting the application. To use, select the "Live Coding (Experimental)" mode from the drop down menu next to the editor's compile button, or type "LiveCoding" into the console for a monolithic build. Press Ctrl+Alt+F11 to find changes and compile. Changes vs standalone Live++ version: * UBT is used to execute builds. This allows standard UE4 adaptive unity mode, allows us to reuse object files when we do regular builds, supports using any build executor allowed by UBT (XGE, SNDBS, etc..). * Adding new source files is supported. * Custom visualizer for FNames is supported via a weakly linked symbol in a static library (Engine/Extras/NatvisHelpers). * Settings are exposed in the editor's project settings dialog. * Standalone application has been rewritten as a Slate app ("LiveCodingConsole"). There is an additional option to start the program as hidden, where it will not be visible until Ctrl+Alt+F11 is hit. Similarly, closing the window will hide it instead of closing the application. * Does not require a standalone licensed version of Live++. Known issues: * Does not currently support class layout changes / object reinstancing #rb none [FYI] Marc.Audy, Stefan.Boberg, Nick.Penwarden #jira #ROBOMERGE-OWNER: ryan.vance #ROBOMERGE-AUTHOR: ben.marsh #ROBOMERGE-SOURCE: CL 5304722 in //UE4/Release-4.22/... via CL 5309051 #ROBOMERGE-BOT: DEVVR (Main -> Dev-VR) [CL 5329502 by ben marsh in Dev-VR branch]
2019-03-06 18:34:25 -05:00
namespace
{
scheduler::TaskQueue* g_taskQueue = nullptr;
scheduler::WorkerThread** g_workerThreads = nullptr;
static bool EmptyTask(void)
{
return true;
}
static unsigned int GetLogicalProcessorCount(void)
{
SYSTEM_INFO info = {};
::GetSystemInfo(&info);
return info.dwNumberOfProcessors;
}
static unsigned int GetPhysicalProcessorCount(void)
{
// try getting the number of physical cores
SYSTEM_LOGICAL_PROCESSOR_INFORMATION* buffer = nullptr;
DWORD bytesNeeded = 0u;
BOOL result = ::GetLogicalProcessorInformation(buffer, &bytesNeeded);
if (result == Windows::FALSE)
{
if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
// function is available. allocate a buffer large enough to hold the information
buffer = static_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION*>(::malloc(bytesNeeded));
result = ::GetLogicalProcessorInformation(buffer, &bytesNeeded);
// return the number of logical processors in case anything went wrong
if ((result == Windows::FALSE) || (buffer == nullptr))
Integrating live coding feature (aka Live++) into UE4. Allows fast iteration of C++ changes without restarting the application. To use, select the "Live Coding (Experimental)" mode from the drop down menu next to the editor's compile button, or type "LiveCoding" into the console for a monolithic build. Press Ctrl+Alt+F11 to find changes and compile. Changes vs standalone Live++ version: * UBT is used to execute builds. This allows standard UE4 adaptive unity mode, allows us to reuse object files when we do regular builds, supports using any build executor allowed by UBT (XGE, SNDBS, etc..). * Adding new source files is supported. * Custom visualizer for FNames is supported via a weakly linked symbol in a static library (Engine/Extras/NatvisHelpers). * Settings are exposed in the editor's project settings dialog. * Standalone application has been rewritten as a Slate app ("LiveCodingConsole"). There is an additional option to start the program as hidden, where it will not be visible until Ctrl+Alt+F11 is hit. Similarly, closing the window will hide it instead of closing the application. * Does not require a standalone licensed version of Live++. Known issues: * Does not currently support class layout changes / object reinstancing #rb none [FYI] Marc.Audy, Stefan.Boberg, Nick.Penwarden #jira #ROBOMERGE-OWNER: ryan.vance #ROBOMERGE-AUTHOR: ben.marsh #ROBOMERGE-SOURCE: CL 5304722 in //UE4/Release-4.22/... via CL 5309051 #ROBOMERGE-BOT: DEVVR (Main -> Dev-VR) [CL 5329502 by ben marsh in Dev-VR branch]
2019-03-06 18:34:25 -05:00
{
::free(buffer);
return GetLogicalProcessorCount();
}
SYSTEM_LOGICAL_PROCESSOR_INFORMATION* info = buffer;
unsigned int coreCount = 0u;
DWORD byteOffset = 0u;
// retrieve relationship while there is still info left in the buffer
while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= bytesNeeded)
{
switch (info->Relationship)
{
case RelationProcessorCore:
++coreCount;
break;
case RelationNumaNode:
case RelationCache:
case RelationProcessorPackage:
case RelationGroup:
case RelationAll:
default:
break;
}
byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
++info;
}
::free(buffer);
// return the number of logical processors in case anything went wrong
if (coreCount == 0u)
{
return GetLogicalProcessorCount();
}
return coreCount;
}
}
// if we cannot retrieve the physical processor information, at least return some
// meaningful number.
return GetLogicalProcessorCount();
}
}
void scheduler::Startup(void)
{
// first create the task queue, and then create a worker thread for each core in the system
g_taskQueue = new scheduler::TaskQueue;
const unsigned int coreCount = GetPhysicalProcessorCount();
g_workerThreads = new scheduler::WorkerThread*[coreCount];
for (unsigned int i = 0u; i < coreCount; ++i)
{
g_workerThreads[i] = new scheduler::WorkerThread(g_taskQueue);
}
}
void scheduler::Shutdown(void)
{
// we deliberately do not destroy the worker threads because we don't want them to be joined.
// we need to exit as fast as possible.
delete g_taskQueue;
}
scheduler::TaskBase* scheduler::CreateEmptyTask(void)
{
return new Task<bool>(&EmptyTask);
}
void scheduler::DestroyTask(TaskBase* task)
{
delete task;
}
void scheduler::RunTask(TaskBase* task)
{
g_taskQueue->PushTask(task);
}
void scheduler::WaitForTask(TaskBase* task)
{
while (!task->IsFinished())
{
// help with other tasks in the mean time, if possible
TaskBase* newTask = g_taskQueue->TryPopTask();
if (newTask)
{
newTask->Execute();
}
else
{
// no task available
thread::Sleep(10u);
}
}
}
// BEGIN EPIC MODS
#pragma warning(pop)
// END EPIC MODS