Improve load screen responsiveness

This commit is contained in:
elasota
2020-11-01 20:59:52 -05:00
parent 47be9d73e3
commit 475b8d21fb
13 changed files with 485 additions and 44 deletions

View File

@@ -105,6 +105,7 @@ LOCAL_SRC_FILES := \
UTF16.cpp \
WindowDef.cpp \
WindowManager.cpp \
WorkerThread.cpp \
XModemCRC.cpp \
ZipFileProxy.cpp

View File

@@ -6,6 +6,10 @@
#error "CreateMutex was macrod"
#endif
#ifdef CreateThread
#error "CreateThread was macrod"
#endif
namespace PortabilityLayer
{
class HostMutex;
@@ -14,16 +18,20 @@ namespace PortabilityLayer
class HostSystemServices
{
public:
typedef int (*ThreadFunc_t)(void *context);
virtual int64_t GetTime() const = 0;
virtual void GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const = 0;
virtual HostMutex *CreateMutex() = 0;
virtual HostMutex *CreateRecursiveMutex() = 0;
virtual void *CreateThread(ThreadFunc_t threadFunc, void *context) = 0;
virtual HostThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) = 0;
virtual uint64_t GetFreeMemoryCosmetic() const = 0; // Returns free memory in bytes, does not have to be accurate
virtual void Beep() const = 0;
virtual bool IsTouchscreen() const = 0;
virtual bool IsUsingMouseAsTouch() const = 0;
virtual bool IsTextInputObstructive() const = 0;
virtual unsigned int GetCPUCount() const = 0;
static void SetInstance(HostSystemServices *instance);
static HostSystemServices *GetInstance();

View File

@@ -165,6 +165,7 @@
<ClInclude Include="PLUnalignedPtr.h" />
<ClInclude Include="PLWidgets.h" />
<ClInclude Include="ResolveCachingColor.h" />
<ClInclude Include="WorkerThread.h" />
<ClInclude Include="TextPlacer.h" />
<ClInclude Include="UTF16.h" />
<ClInclude Include="UTF8.h" />
@@ -320,6 +321,7 @@
<ClCompile Include="UTF8.cpp" />
<ClCompile Include="WindowDef.cpp" />
<ClCompile Include="WindowManager.cpp" />
<ClCompile Include="WorkerThread.cpp" />
<ClCompile Include="XModemCRC.cpp" />
<ClCompile Include="ZipFileProxy.cpp" />
</ItemGroup>

View File

@@ -462,6 +462,9 @@
<ClInclude Include="FileBrowserUI.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="WorkerThread.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="CFileStream.cpp">
@@ -737,5 +740,8 @@
<ClCompile Include="FileBrowserUI.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="WorkerThread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,152 @@
#include "WorkerThread.h"
#include "HostSystemServices.h"
#include "HostThreadEvent.h"
#include <stdlib.h>
#include <new>
namespace PortabilityLayer
{
class WorkerThreadImpl final : public WorkerThread
{
public:
WorkerThreadImpl();
bool Init();
void Destroy() override;
void AsyncExecuteTask(Callback_t callback, void *context) override;
private:
~WorkerThreadImpl() override;
static int StaticThreadFuncThunk(void *context);
int ThreadFunc();
HostThreadEvent *m_wakeSignal;
HostThreadEvent *m_wakeConsumedSignal;
Callback_t m_waitingCallback;
void *m_waitingContext;
bool m_terminated;
bool m_threadRunning;
};
}
void PortabilityLayer::WorkerThreadImpl::Destroy()
{
this->~WorkerThreadImpl();
free(this);
}
void PortabilityLayer::WorkerThreadImpl::AsyncExecuteTask(PortabilityLayer::WorkerThread::Callback_t callback, void *context)
{
m_waitingCallback = callback;
m_waitingContext = context;
m_wakeSignal->Signal();
m_wakeConsumedSignal->Wait();
}
PortabilityLayer::WorkerThreadImpl::WorkerThreadImpl()
: m_wakeSignal(nullptr)
, m_wakeConsumedSignal(nullptr)
, m_waitingCallback(nullptr)
, m_waitingContext(nullptr)
, m_terminated(false)
, m_threadRunning(false)
{
}
PortabilityLayer::WorkerThreadImpl::~WorkerThreadImpl()
{
if (m_threadRunning)
{
m_terminated = true;
m_wakeSignal->Signal();
m_wakeConsumedSignal->Wait();
}
if (m_wakeSignal)
m_wakeSignal->Destroy();
if (m_wakeConsumedSignal)
m_wakeConsumedSignal->Destroy();
}
int PortabilityLayer::WorkerThreadImpl::StaticThreadFuncThunk(void *context)
{
return static_cast<PortabilityLayer::WorkerThreadImpl*>(context)->ThreadFunc();
}
int PortabilityLayer::WorkerThreadImpl::ThreadFunc()
{
m_wakeSignal->Wait();
m_wakeConsumedSignal->Signal();
for (;;)
{
m_wakeSignal->Wait();
if (m_terminated)
{
m_wakeConsumedSignal->Signal();
return 0;
}
else
{
Callback_t callback = m_waitingCallback;
void *context = m_waitingContext;
m_wakeConsumedSignal->Signal();
callback(context);
}
}
}
bool PortabilityLayer::WorkerThreadImpl::Init()
{
HostSystemServices *sysServices = HostSystemServices::GetInstance();
m_wakeSignal = sysServices->CreateThreadEvent(true, false);
if (!m_wakeSignal)
return false;
m_wakeConsumedSignal = sysServices->CreateThreadEvent(true, false);
if (!m_wakeConsumedSignal)
return false;
if (!sysServices->CreateThread(PortabilityLayer::WorkerThreadImpl::StaticThreadFuncThunk, this))
return false;
m_threadRunning = true;
m_wakeSignal->Signal();
m_wakeConsumedSignal->Wait();
return true;
}
PortabilityLayer::WorkerThread::WorkerThread()
{
}
PortabilityLayer::WorkerThread::~WorkerThread()
{
}
PortabilityLayer::WorkerThread *PortabilityLayer::WorkerThread::Create()
{
void *storage = malloc(sizeof(PortabilityLayer::WorkerThreadImpl));
if (!storage)
return nullptr;
PortabilityLayer::WorkerThreadImpl *thread = new (storage) PortabilityLayer::WorkerThreadImpl();
if (!thread->Init())
{
thread->Destroy();
return nullptr;
}
return thread;
}

View File

@@ -0,0 +1,23 @@
#pragma once
#include <stdint.h>
namespace PortabilityLayer
{
class HostThreadEvent;
class WorkerThread
{
public:
typedef void(*Callback_t)(void *context);
static WorkerThread *Create();
virtual void Destroy() = 0;
virtual void AsyncExecuteTask(Callback_t callback, void *context) = 0;
protected:
WorkerThread();
virtual ~WorkerThread();
};
}