mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-12-14 12:09:36 +00:00
Improve load screen responsiveness
This commit is contained in:
@@ -9,6 +9,26 @@
|
|||||||
#undef CreateMutex
|
#undef CreateMutex
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct GpSystemServices_Win32_ThreadStartParams
|
||||||
|
{
|
||||||
|
GpSystemServices_Win32::ThreadFunc_t m_threadFunc;
|
||||||
|
void *m_threadContext;
|
||||||
|
PortabilityLayer::HostThreadEvent *m_threadStartEvent;
|
||||||
|
};
|
||||||
|
|
||||||
|
static DWORD WINAPI StaticStartThread(LPVOID lpThreadParameter)
|
||||||
|
{
|
||||||
|
const GpSystemServices_Win32_ThreadStartParams *threadParams = static_cast<const GpSystemServices_Win32_ThreadStartParams*>(lpThreadParameter);
|
||||||
|
|
||||||
|
GpSystemServices_Win32::ThreadFunc_t threadFunc = threadParams->m_threadFunc;
|
||||||
|
void *threadContext = threadParams->m_threadContext;
|
||||||
|
PortabilityLayer::HostThreadEvent *threadStartEvent = threadParams->m_threadStartEvent;
|
||||||
|
|
||||||
|
threadStartEvent->Signal();
|
||||||
|
|
||||||
|
return threadFunc(threadContext);
|
||||||
|
}
|
||||||
|
|
||||||
GpSystemServices_Win32::GpSystemServices_Win32()
|
GpSystemServices_Win32::GpSystemServices_Win32()
|
||||||
: m_isTouchscreenSimulation(false)
|
: m_isTouchscreenSimulation(false)
|
||||||
{
|
{
|
||||||
@@ -67,6 +87,30 @@ PortabilityLayer::HostThreadEvent *GpSystemServices_Win32::CreateThreadEvent(boo
|
|||||||
return GpThreadEvent_Win32::Create(autoReset, startSignaled);
|
return GpThreadEvent_Win32::Create(autoReset, startSignaled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *GpSystemServices_Win32::CreateThread(ThreadFunc_t threadFunc, void *context)
|
||||||
|
{
|
||||||
|
PortabilityLayer::HostThreadEvent *evt = CreateThreadEvent(true, false);
|
||||||
|
if (!evt)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
GpSystemServices_Win32_ThreadStartParams startParams;
|
||||||
|
startParams.m_threadContext = context;
|
||||||
|
startParams.m_threadFunc = threadFunc;
|
||||||
|
startParams.m_threadStartEvent = evt;
|
||||||
|
|
||||||
|
HANDLE threadHdl = ::CreateThread(nullptr, 0, StaticStartThread, &startParams, 0, nullptr);
|
||||||
|
if (threadHdl == nullptr)
|
||||||
|
{
|
||||||
|
evt->Destroy();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
evt->Wait();
|
||||||
|
evt->Destroy();
|
||||||
|
|
||||||
|
return threadHdl;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t GpSystemServices_Win32::GetFreeMemoryCosmetic() const
|
uint64_t GpSystemServices_Win32::GetFreeMemoryCosmetic() const
|
||||||
{
|
{
|
||||||
MEMORYSTATUSEX memStatus;
|
MEMORYSTATUSEX memStatus;
|
||||||
@@ -100,6 +144,13 @@ bool GpSystemServices_Win32::IsTextInputObstructive() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int GpSystemServices_Win32::GetCPUCount() const
|
||||||
|
{
|
||||||
|
SYSTEM_INFO sysInfo;
|
||||||
|
GetSystemInfo(&sysInfo);
|
||||||
|
return sysInfo.dwNumberOfProcessors;
|
||||||
|
}
|
||||||
|
|
||||||
void GpSystemServices_Win32::SetTouchscreenSimulation(bool isTouchscreenSimulation)
|
void GpSystemServices_Win32::SetTouchscreenSimulation(bool isTouchscreenSimulation)
|
||||||
{
|
{
|
||||||
m_isTouchscreenSimulation = isTouchscreenSimulation;
|
m_isTouchscreenSimulation = isTouchscreenSimulation;
|
||||||
|
|||||||
@@ -9,6 +9,11 @@
|
|||||||
#undef CreateMutex
|
#undef CreateMutex
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#pragma push_macro("CreateThread")
|
||||||
|
#ifdef CreateThread
|
||||||
|
#undef CreateThread
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class GpSystemServices_Win32 final : public PortabilityLayer::HostSystemServices
|
class GpSystemServices_Win32 final : public PortabilityLayer::HostSystemServices
|
||||||
{
|
{
|
||||||
@@ -19,12 +24,14 @@ public:
|
|||||||
void GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const override;
|
void GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const override;
|
||||||
PortabilityLayer::HostMutex *CreateMutex() override;
|
PortabilityLayer::HostMutex *CreateMutex() override;
|
||||||
PortabilityLayer::HostMutex *CreateRecursiveMutex() override;
|
PortabilityLayer::HostMutex *CreateRecursiveMutex() override;
|
||||||
|
void *CreateThread(ThreadFunc_t threadFunc, void *context) override;
|
||||||
PortabilityLayer::HostThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) override;
|
PortabilityLayer::HostThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) override;
|
||||||
uint64_t GetFreeMemoryCosmetic() const override;
|
uint64_t GetFreeMemoryCosmetic() const override;
|
||||||
void Beep() const override;
|
void Beep() const override;
|
||||||
bool IsTouchscreen() const override;
|
bool IsTouchscreen() const override;
|
||||||
bool IsUsingMouseAsTouch() const override;
|
bool IsUsingMouseAsTouch() const override;
|
||||||
bool IsTextInputObstructive() const override;
|
bool IsTextInputObstructive() const override;
|
||||||
|
unsigned int GetCPUCount() const override;
|
||||||
|
|
||||||
void SetTouchscreenSimulation(bool isTouchscreenSimulation);
|
void SetTouchscreenSimulation(bool isTouchscreenSimulation);
|
||||||
|
|
||||||
@@ -37,3 +44,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#pragma pop_macro("CreateMutex")
|
#pragma pop_macro("CreateMutex")
|
||||||
|
#pragma pop_macro("CreateThread")
|
||||||
|
|||||||
@@ -1,10 +1,32 @@
|
|||||||
#include "GpSystemServices_Android.h"
|
#include "GpSystemServices_Android.h"
|
||||||
#include "HostMutex.h"
|
#include "HostMutex.h"
|
||||||
#include "HostThreadEvent.h"
|
#include "HostThreadEvent.h"
|
||||||
|
#include "SDL.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
struct GpSystemServices_Android_ThreadStartParams
|
||||||
|
{
|
||||||
|
GpSystemServices_Android::ThreadFunc_t m_threadFunc;
|
||||||
|
void *m_threadContext;
|
||||||
|
PortabilityLayer::HostThreadEvent *m_threadStartEvent;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int SDLCALL StaticStartThread(void *lpThreadParameter)
|
||||||
|
{
|
||||||
|
const GpSystemServices_Android_ThreadStartParams *threadParams = static_cast<const GpSystemServices_Android_ThreadStartParams*>(lpThreadParameter);
|
||||||
|
|
||||||
|
GpSystemServices_Android::ThreadFunc_t threadFunc = threadParams->m_threadFunc;
|
||||||
|
void *threadContext = threadParams->m_threadContext;
|
||||||
|
PortabilityLayer::HostThreadEvent *threadStartEvent = threadParams->m_threadStartEvent;
|
||||||
|
|
||||||
|
threadStartEvent->Signal();
|
||||||
|
|
||||||
|
return threadFunc(threadContext);
|
||||||
|
}
|
||||||
|
|
||||||
template<class TMutex>
|
template<class TMutex>
|
||||||
class GpMutex_Cpp11 final : public PortabilityLayer::HostMutex
|
class GpMutex_Cpp11 final : public PortabilityLayer::HostMutex
|
||||||
@@ -173,6 +195,31 @@ PortabilityLayer::HostMutex *GpSystemServices_Android::CreateMutex()
|
|||||||
return new (mutex) GpMutex_Cpp11_Vanilla();
|
return new (mutex) GpMutex_Cpp11_Vanilla();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *GpSystemServices_Android::CreateThread(ThreadFunc_t threadFunc, void *context)
|
||||||
|
{
|
||||||
|
PortabilityLayer::HostThreadEvent *evt = CreateThreadEvent(true, false);
|
||||||
|
if (!evt)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
GpSystemServices_Android_ThreadStartParams startParams;
|
||||||
|
startParams.m_threadContext = context;
|
||||||
|
startParams.m_threadFunc = threadFunc;
|
||||||
|
startParams.m_threadStartEvent = evt;
|
||||||
|
|
||||||
|
SDL_Thread *thread = SDL_CreateThread(StaticStartThread, "WorkerThread", &startParams);
|
||||||
|
if (thread == nullptr)
|
||||||
|
{
|
||||||
|
evt->Destroy();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
evt->Wait();
|
||||||
|
evt->Destroy();
|
||||||
|
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
|
||||||
PortabilityLayer::HostMutex *GpSystemServices_Android::CreateRecursiveMutex()
|
PortabilityLayer::HostMutex *GpSystemServices_Android::CreateRecursiveMutex()
|
||||||
{
|
{
|
||||||
GpMutex_Cpp11_Recursive *mutex = static_cast<GpMutex_Cpp11_Recursive*>(malloc(sizeof(GpMutex_Cpp11_Recursive)));
|
GpMutex_Cpp11_Recursive *mutex = static_cast<GpMutex_Cpp11_Recursive*>(malloc(sizeof(GpMutex_Cpp11_Recursive)));
|
||||||
@@ -193,7 +240,9 @@ PortabilityLayer::HostThreadEvent *GpSystemServices_Android::CreateThreadEvent(b
|
|||||||
|
|
||||||
uint64_t GpSystemServices_Android::GetFreeMemoryCosmetic() const
|
uint64_t GpSystemServices_Android::GetFreeMemoryCosmetic() const
|
||||||
{
|
{
|
||||||
return 0;
|
long pages = sysconf(_SC_AVPHYS_PAGES);
|
||||||
|
long pageSize = sysconf(_SC_PAGE_SIZE);
|
||||||
|
return pages * pageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpSystemServices_Android::Beep() const
|
void GpSystemServices_Android::Beep() const
|
||||||
@@ -215,6 +264,11 @@ bool GpSystemServices_Android::IsTextInputObstructive() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int GpSystemServices_Android::GetCPUCount() const
|
||||||
|
{
|
||||||
|
return SDL_GetCPUCount();
|
||||||
|
}
|
||||||
|
|
||||||
GpSystemServices_Android *GpSystemServices_Android::GetInstance()
|
GpSystemServices_Android *GpSystemServices_Android::GetInstance()
|
||||||
{
|
{
|
||||||
return &ms_instance;
|
return &ms_instance;
|
||||||
|
|||||||
@@ -12,12 +12,14 @@ public:
|
|||||||
void GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const override;
|
void GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const override;
|
||||||
PortabilityLayer::HostMutex *CreateMutex() override;
|
PortabilityLayer::HostMutex *CreateMutex() override;
|
||||||
PortabilityLayer::HostMutex *CreateRecursiveMutex() override;
|
PortabilityLayer::HostMutex *CreateRecursiveMutex() override;
|
||||||
|
void *CreateThread(ThreadFunc_t threadFunc, void *context) override;
|
||||||
PortabilityLayer::HostThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) override;
|
PortabilityLayer::HostThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) override;
|
||||||
uint64_t GetFreeMemoryCosmetic() const override;
|
uint64_t GetFreeMemoryCosmetic() const override;
|
||||||
void Beep() const override;
|
void Beep() const override;
|
||||||
bool IsTouchscreen() const override;
|
bool IsTouchscreen() const override;
|
||||||
bool IsUsingMouseAsTouch() const override;
|
bool IsUsingMouseAsTouch() const override;
|
||||||
bool IsTextInputObstructive() const override;
|
bool IsTextInputObstructive() const override;
|
||||||
|
unsigned int GetCPUCount() const override;
|
||||||
|
|
||||||
static GpSystemServices_Android *GetInstance();
|
static GpSystemServices_Android *GetInstance();
|
||||||
|
|
||||||
|
|||||||
BIN
ApplicationResourcePatches/PICT/1302.bmp
Normal file
BIN
ApplicationResourcePatches/PICT/1302.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -11,6 +11,7 @@
|
|||||||
"DITL/2006.json" : "ApplicationResourcePatches/DITL/2006.json",
|
"DITL/2006.json" : "ApplicationResourcePatches/DITL/2006.json",
|
||||||
"PICT/1300.bmp" : "ApplicationResourcePatches/PICT/1300.bmp",
|
"PICT/1300.bmp" : "ApplicationResourcePatches/PICT/1300.bmp",
|
||||||
"PICT/1301.bmp" : "ApplicationResourcePatches/PICT/1301.bmp",
|
"PICT/1301.bmp" : "ApplicationResourcePatches/PICT/1301.bmp",
|
||||||
|
"PICT/1302.bmp" : "ApplicationResourcePatches/PICT/1302.bmp",
|
||||||
"PICT/1971.bmp" : "ApplicationResourcePatches/PICT/1971.bmp",
|
"PICT/1971.bmp" : "ApplicationResourcePatches/PICT/1971.bmp",
|
||||||
"PICT/1972.bmp" : "ApplicationResourcePatches/PICT/1972.bmp",
|
"PICT/1972.bmp" : "ApplicationResourcePatches/PICT/1972.bmp",
|
||||||
"PICT/1973.bmp" : "ApplicationResourcePatches/PICT/1973.bmp",
|
"PICT/1973.bmp" : "ApplicationResourcePatches/PICT/1973.bmp",
|
||||||
|
|||||||
191
GpApp/Main.cpp
191
GpApp/Main.cpp
@@ -6,7 +6,8 @@
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
|
||||||
#include <WindowDef.h>
|
#include "WindowDef.h"
|
||||||
|
#include "BitmapImage.h"
|
||||||
#include "PLApplication.h"
|
#include "PLApplication.h"
|
||||||
#include "PLKeyEncoding.h"
|
#include "PLKeyEncoding.h"
|
||||||
#include "PLStandardColors.h"
|
#include "PLStandardColors.h"
|
||||||
@@ -16,19 +17,30 @@
|
|||||||
#include "FontFamily.h"
|
#include "FontFamily.h"
|
||||||
#include "GpRenderedFontMetrics.h"
|
#include "GpRenderedFontMetrics.h"
|
||||||
#include "HostDisplayDriver.h"
|
#include "HostDisplayDriver.h"
|
||||||
|
#include "HostSystemServices.h"
|
||||||
|
#include "HostThreadEvent.h"
|
||||||
#include "IGpDisplayDriver.h"
|
#include "IGpDisplayDriver.h"
|
||||||
#include "GpIOStream.h"
|
#include "GpIOStream.h"
|
||||||
#include "House.h"
|
#include "House.h"
|
||||||
#include "MainMenuUI.h"
|
#include "MainMenuUI.h"
|
||||||
|
#include "MemoryManager.h"
|
||||||
#include "MenuManager.h"
|
#include "MenuManager.h"
|
||||||
|
#include "QDPixMap.h"
|
||||||
#include "RenderedFont.h"
|
#include "RenderedFont.h"
|
||||||
#include "ResolveCachingColor.h"
|
#include "ResolveCachingColor.h"
|
||||||
|
#include "ResourceManager.h"
|
||||||
|
#include "Utilities.h"
|
||||||
#include "WindowManager.h"
|
#include "WindowManager.h"
|
||||||
|
#include "WorkerThread.h"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
|
||||||
|
int loadScreenRingStep;
|
||||||
WindowPtr loadScreenWindow;
|
WindowPtr loadScreenWindow;
|
||||||
Rect loadScreenProgressBarRect;
|
Rect loadScreenProgressBarRect;
|
||||||
int loadScreenProgress;
|
int loadScreenProgress;
|
||||||
|
DrawSurface *loadScreenRingSurface;
|
||||||
|
|
||||||
|
|
||||||
#define kPrefsVersion 0x0038
|
#define kPrefsVersion 0x0038
|
||||||
@@ -345,6 +357,23 @@ void WriteOutPrefs (void)
|
|||||||
UnivSetSoundVolume(wasVolume, thisMac.hasSM3);
|
UnivSetSoundVolume(wasVolume, thisMac.hasSM3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StepLoadScreenRing()
|
||||||
|
{
|
||||||
|
if (loadScreenWindow)
|
||||||
|
{
|
||||||
|
const int loadScreenStepGranularity = 2;
|
||||||
|
loadScreenRingStep++;
|
||||||
|
if (loadScreenRingStep == 24 * loadScreenStepGranularity)
|
||||||
|
loadScreenRingStep = 0;
|
||||||
|
|
||||||
|
Rect ringDestRect = Rect::Create(8, 8, 24, 24);
|
||||||
|
Rect ringSrcRect = Rect::Create(0, 0, 16, 16) + Point::Create((loadScreenRingStep / loadScreenStepGranularity) * 16, 0);
|
||||||
|
|
||||||
|
CopyBits(*loadScreenRingSurface->m_port.GetPixMap(), *loadScreenWindow->GetDrawSurface()->m_port.GetPixMap(), &ringSrcRect, &ringDestRect, srcCopy);
|
||||||
|
loadScreenWindow->GetDrawSurface()->m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void StepLoadScreen(int steps)
|
void StepLoadScreen(int steps)
|
||||||
{
|
{
|
||||||
if (loadScreenWindow)
|
if (loadScreenWindow)
|
||||||
@@ -362,8 +391,14 @@ void StepLoadScreen(int steps)
|
|||||||
|
|
||||||
loadScreenWindow->GetDrawSurface()->FillRect(Rect::Create(loadScreenProgressBarRect.top, loadScreenProgressBarRect.left + prevStep, loadScreenProgressBarRect.bottom, loadScreenProgressBarRect.left + thisStep), blackColor);
|
loadScreenWindow->GetDrawSurface()->FillRect(Rect::Create(loadScreenProgressBarRect.top, loadScreenProgressBarRect.left + prevStep, loadScreenProgressBarRect.bottom, loadScreenProgressBarRect.left + thisStep), blackColor);
|
||||||
ForceSyncFrame();
|
ForceSyncFrame();
|
||||||
}
|
|
||||||
|
|
||||||
|
for (int i = 0; i < steps; i++)
|
||||||
|
{
|
||||||
|
StepLoadScreenRing();
|
||||||
|
Delay(1, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
SpinCursor(steps);
|
SpinCursor(steps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,19 +409,28 @@ void InitLoadingWindow()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
static const int kLoadScreenHeight = 32;
|
static const int kLoadScreenHeight = 32;
|
||||||
|
static const int kLoadRingResource = 1302;
|
||||||
|
|
||||||
int kLoadScreenWidth = 256;
|
int kLoadScreenWidth = 296;
|
||||||
PLPasStr loadingText = PSTR("Loading...");
|
PLPasStr loadingText = PSTR("Loading...");
|
||||||
|
|
||||||
if (!isPrefsLoaded)
|
if (!isPrefsLoaded)
|
||||||
{
|
{
|
||||||
loadingText = PSTR("Performing First-Time Setup...");
|
loadingText = PSTR("Performing First-Time Setup...");
|
||||||
kLoadScreenWidth = 420;
|
kLoadScreenWidth = 440;
|
||||||
}
|
}
|
||||||
|
|
||||||
ForceSyncFrame();
|
ForceSyncFrame();
|
||||||
PLSysCalls::Sleep(1);
|
PLSysCalls::Sleep(1);
|
||||||
|
|
||||||
|
THandle<BitmapImage> loadRingImageH = PortabilityLayer::ResourceManager::GetInstance()->GetAppResource('PICT', kLoadRingResource).StaticCast<BitmapImage>();
|
||||||
|
BitmapImage *loadRingImage = *loadRingImageH;
|
||||||
|
|
||||||
|
DrawSurface *loadRingSurface = nullptr;
|
||||||
|
Rect loadRingRect = loadRingImage->GetRect();
|
||||||
|
CreateOffScreenGWorld(&loadRingSurface, &loadRingRect);
|
||||||
|
loadRingSurface->DrawPicture(loadRingImageH, loadRingRect);
|
||||||
|
|
||||||
int32_t lsX = (thisMac.fullScreen.Width() - kLoadScreenWidth) / 2;
|
int32_t lsX = (thisMac.fullScreen.Width() - kLoadScreenWidth) / 2;
|
||||||
int32_t lsY = (thisMac.fullScreen.Height() - kLoadScreenHeight) / 2;
|
int32_t lsY = (thisMac.fullScreen.Height() - kLoadScreenHeight) / 2;
|
||||||
|
|
||||||
@@ -409,21 +453,27 @@ void InitLoadingWindow()
|
|||||||
|
|
||||||
PortabilityLayer::RenderedFont *font = GetApplicationFont(18, PortabilityLayer::FontFamilyFlag_None, true);
|
PortabilityLayer::RenderedFont *font = GetApplicationFont(18, PortabilityLayer::FontFamilyFlag_None, true);
|
||||||
int32_t textY = (kLoadScreenHeight + font->GetMetrics().m_ascent) / 2;
|
int32_t textY = (kLoadScreenHeight + font->GetMetrics().m_ascent) / 2;
|
||||||
surface->DrawString(Point::Create(4+16, textY), loadingText, blackColor, font);
|
surface->DrawString(Point::Create(4+16+8, textY), loadingText, blackColor, font);
|
||||||
|
|
||||||
static const int32_t loadBarPadding = 16;
|
static const int32_t loadBarPadding = 16;
|
||||||
int32_t loadBarStartX = static_cast<int32_t>(font->MeasureString(loadingText.UChars(), loadingText.Length())) + 4 + 16 + loadBarPadding;
|
int32_t loadBarStartX = static_cast<int32_t>(font->MeasureString(loadingText.UChars(), loadingText.Length())) + 4 + 16 + 8 + loadBarPadding;
|
||||||
int32_t loadBarEndX = loadScreenLocalRect.right - loadBarPadding;
|
int32_t loadBarEndX = loadScreenLocalRect.right - loadBarPadding;
|
||||||
|
|
||||||
loadScreenProgressBarRect = Rect::Create((loadScreenLocalRect.Height() - 8) / 2, loadBarStartX, (loadScreenLocalRect.Height() + 8) / 2, loadBarEndX);
|
loadScreenProgressBarRect = Rect::Create((loadScreenLocalRect.Height() - 8) / 2, loadBarStartX, (loadScreenLocalRect.Height() + 8) / 2, loadBarEndX);
|
||||||
loadScreenProgress = 0;
|
loadScreenProgress = 0;
|
||||||
|
|
||||||
surface->FrameRect(loadScreenProgressBarRect, blackColor);
|
surface->FrameRect(loadScreenProgressBarRect, blackColor);
|
||||||
|
|
||||||
|
Rect ringDestRect = Rect::Create(8, 8, 24, 24);
|
||||||
|
Rect ringSrcRect = Rect::Create(0, 0, 16, 16);
|
||||||
|
CopyBits(*loadRingSurface->m_port.GetPixMap(), *surface->m_port.GetPixMap(), &ringSrcRect, &ringDestRect, srcCopy);
|
||||||
|
|
||||||
|
loadRingImageH.Dispose();
|
||||||
|
|
||||||
|
loadScreenRingSurface = loadRingSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreloadFonts()
|
enum PreloadFontCategory
|
||||||
{
|
|
||||||
enum FontCategory
|
|
||||||
{
|
{
|
||||||
FontCategory_System,
|
FontCategory_System,
|
||||||
FontCategory_Application,
|
FontCategory_Application,
|
||||||
@@ -431,37 +481,42 @@ void PreloadFonts()
|
|||||||
FontCategory_Monospace,
|
FontCategory_Monospace,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FontSpec
|
struct PreloadFontSpec
|
||||||
{
|
{
|
||||||
FontCategory m_category;
|
PreloadFontCategory m_category;
|
||||||
int m_size;
|
int m_size;
|
||||||
int m_flags;
|
int m_flags;
|
||||||
bool m_aa;
|
bool m_aa;
|
||||||
};
|
};
|
||||||
|
|
||||||
FontSpec specs[] =
|
struct PreloadFontWorkSlot
|
||||||
{
|
{
|
||||||
{ FontCategory_System, 9, PortabilityLayer::FontFamilyFlag_Bold, true },
|
PortabilityLayer::HostThreadEvent *m_completedEvent;
|
||||||
{ FontCategory_System, 10, PortabilityLayer::FontFamilyFlag_Bold, true },
|
PortabilityLayer::WorkerThread *m_workerThread;
|
||||||
{ FontCategory_System, 12, PortabilityLayer::FontFamilyFlag_None, true },
|
std::atomic<int> m_singleJobCompleted;
|
||||||
{ FontCategory_System, 12, PortabilityLayer::FontFamilyFlag_Bold, true },
|
const PreloadFontSpec *m_spec;
|
||||||
{ FontCategory_Application, 8, PortabilityLayer::FontFamilyFlag_None, true },
|
bool m_queued;
|
||||||
{ FontCategory_Application, 9, PortabilityLayer::FontFamilyFlag_None, true },
|
|
||||||
{ FontCategory_Application, 12, PortabilityLayer::FontFamilyFlag_Bold, true },
|
PreloadFontWorkSlot();
|
||||||
{ FontCategory_Application, 14, PortabilityLayer::FontFamilyFlag_Bold, true },
|
~PreloadFontWorkSlot();
|
||||||
{ FontCategory_Application, 18, PortabilityLayer::FontFamilyFlag_None, true },
|
|
||||||
{ FontCategory_Application, 40, PortabilityLayer::FontFamilyFlag_None, true },
|
|
||||||
{ FontCategory_Handwriting, 24, PortabilityLayer::FontFamilyFlag_None, true },
|
|
||||||
{ FontCategory_Handwriting, 48, PortabilityLayer::FontFamilyFlag_None, true },
|
|
||||||
{ FontCategory_Monospace, 10, PortabilityLayer::FontFamilyFlag_None, true },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const int numFontSpecs = sizeof(specs) / sizeof(specs[0]);
|
PreloadFontWorkSlot::PreloadFontWorkSlot()
|
||||||
|
: m_completedEvent(nullptr)
|
||||||
for (int i = 0; i < numFontSpecs; i++)
|
, m_workerThread(nullptr)
|
||||||
|
, m_spec(nullptr)
|
||||||
|
, m_queued(false)
|
||||||
{
|
{
|
||||||
const FontSpec &spec = specs[i];
|
}
|
||||||
|
|
||||||
|
PreloadFontWorkSlot::~PreloadFontWorkSlot()
|
||||||
|
{
|
||||||
|
if (m_workerThread)
|
||||||
|
m_workerThread->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreloadSingleFont (const PreloadFontSpec &spec)
|
||||||
|
{
|
||||||
switch (spec.m_category)
|
switch (spec.m_category)
|
||||||
{
|
{
|
||||||
case FontCategory_Application:
|
case FontCategory_Application:
|
||||||
@@ -479,11 +534,83 @@ void PreloadFonts()
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreloadThreadFunc(void *context)
|
||||||
|
{
|
||||||
|
PreloadFontWorkSlot *wSlot = static_cast<PreloadFontWorkSlot*>(context);
|
||||||
|
|
||||||
|
PreloadSingleFont(*wSlot->m_spec);
|
||||||
|
++wSlot->m_singleJobCompleted;
|
||||||
|
wSlot->m_completedEvent->Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreloadFonts()
|
||||||
|
{
|
||||||
|
static PreloadFontSpec specs[] =
|
||||||
|
{
|
||||||
|
{ FontCategory_System, 9, PortabilityLayer::FontFamilyFlag_Bold, true },
|
||||||
|
{ FontCategory_System, 10, PortabilityLayer::FontFamilyFlag_Bold, true },
|
||||||
|
{ FontCategory_System, 12, PortabilityLayer::FontFamilyFlag_None, true },
|
||||||
|
{ FontCategory_System, 12, PortabilityLayer::FontFamilyFlag_Bold, true },
|
||||||
|
{ FontCategory_Application, 8, PortabilityLayer::FontFamilyFlag_None, true },
|
||||||
|
{ FontCategory_Application, 9, PortabilityLayer::FontFamilyFlag_None, true },
|
||||||
|
{ FontCategory_Application, 12, PortabilityLayer::FontFamilyFlag_Bold, true },
|
||||||
|
{ FontCategory_Application, 14, PortabilityLayer::FontFamilyFlag_Bold, true },
|
||||||
|
{ FontCategory_Application, 18, PortabilityLayer::FontFamilyFlag_None, true },
|
||||||
|
{ FontCategory_Application, 40, PortabilityLayer::FontFamilyFlag_None, true },
|
||||||
|
{ FontCategory_Handwriting, 24, PortabilityLayer::FontFamilyFlag_None, true },
|
||||||
|
{ FontCategory_Handwriting, 48, PortabilityLayer::FontFamilyFlag_None, true },
|
||||||
|
{ FontCategory_Monospace, 10, PortabilityLayer::FontFamilyFlag_None, true },
|
||||||
|
};
|
||||||
|
|
||||||
|
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
||||||
|
|
||||||
|
|
||||||
|
const int numFontSpecs = sizeof(specs) / sizeof(specs[0]);
|
||||||
|
|
||||||
|
int queuedSpecs = 0;
|
||||||
|
int completedSpecs = 0;
|
||||||
|
|
||||||
|
// We can't actually slot these because FT isn't thread-safe when accessing the same font,
|
||||||
|
// but we can do this to unclog the render thread.
|
||||||
|
PreloadFontWorkSlot slot;
|
||||||
|
slot.m_workerThread = PortabilityLayer::WorkerThread::Create();
|
||||||
|
slot.m_completedEvent = PortabilityLayer::HostSystemServices::GetInstance()->CreateThreadEvent(true, false);
|
||||||
|
|
||||||
|
while (completedSpecs < numFontSpecs)
|
||||||
|
{
|
||||||
|
if (slot.m_queued)
|
||||||
|
{
|
||||||
|
if (slot.m_singleJobCompleted.load(std::memory_order_relaxed) != 0)
|
||||||
|
{
|
||||||
|
slot.m_completedEvent->Wait();
|
||||||
|
slot.m_queued = false;
|
||||||
|
completedSpecs++;
|
||||||
|
|
||||||
StepLoadScreen(1);
|
StepLoadScreen(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!slot.m_queued)
|
||||||
|
{
|
||||||
|
if (queuedSpecs < numFontSpecs)
|
||||||
|
{
|
||||||
|
slot.m_queued = true;
|
||||||
|
slot.m_singleJobCompleted.store(0);
|
||||||
|
slot.m_spec = specs + queuedSpecs;
|
||||||
|
slot.m_workerThread->AsyncExecuteTask(PreloadThreadFunc, &slot);
|
||||||
|
|
||||||
|
queuedSpecs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StepLoadScreenRing();
|
||||||
|
Delay(1, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void gpAppInit()
|
void gpAppInit()
|
||||||
{
|
{
|
||||||
// This is called before the display driver is initialized
|
// This is called before the display driver is initialized
|
||||||
@@ -556,6 +683,12 @@ int gpAppMain()
|
|||||||
PLSysCalls::Sleep(15);
|
PLSysCalls::Sleep(15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (loadScreenRingSurface)
|
||||||
|
{
|
||||||
|
DisposeGWorld(loadScreenRingSurface);
|
||||||
|
loadScreenRingSurface = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
OpenMainWindow();
|
OpenMainWindow();
|
||||||
|
|
||||||
if (isDoColorFade)
|
if (isDoColorFade)
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ LOCAL_SRC_FILES := \
|
|||||||
UTF16.cpp \
|
UTF16.cpp \
|
||||||
WindowDef.cpp \
|
WindowDef.cpp \
|
||||||
WindowManager.cpp \
|
WindowManager.cpp \
|
||||||
|
WorkerThread.cpp \
|
||||||
XModemCRC.cpp \
|
XModemCRC.cpp \
|
||||||
ZipFileProxy.cpp
|
ZipFileProxy.cpp
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
#error "CreateMutex was macrod"
|
#error "CreateMutex was macrod"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CreateThread
|
||||||
|
#error "CreateThread was macrod"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace PortabilityLayer
|
namespace PortabilityLayer
|
||||||
{
|
{
|
||||||
class HostMutex;
|
class HostMutex;
|
||||||
@@ -14,16 +18,20 @@ namespace PortabilityLayer
|
|||||||
class HostSystemServices
|
class HostSystemServices
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef int (*ThreadFunc_t)(void *context);
|
||||||
|
|
||||||
virtual int64_t GetTime() const = 0;
|
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 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 *CreateMutex() = 0;
|
||||||
virtual HostMutex *CreateRecursiveMutex() = 0;
|
virtual HostMutex *CreateRecursiveMutex() = 0;
|
||||||
|
virtual void *CreateThread(ThreadFunc_t threadFunc, void *context) = 0;
|
||||||
virtual HostThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) = 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 uint64_t GetFreeMemoryCosmetic() const = 0; // Returns free memory in bytes, does not have to be accurate
|
||||||
virtual void Beep() const = 0;
|
virtual void Beep() const = 0;
|
||||||
virtual bool IsTouchscreen() const = 0;
|
virtual bool IsTouchscreen() const = 0;
|
||||||
virtual bool IsUsingMouseAsTouch() const = 0;
|
virtual bool IsUsingMouseAsTouch() const = 0;
|
||||||
virtual bool IsTextInputObstructive() const = 0;
|
virtual bool IsTextInputObstructive() const = 0;
|
||||||
|
virtual unsigned int GetCPUCount() const = 0;
|
||||||
|
|
||||||
static void SetInstance(HostSystemServices *instance);
|
static void SetInstance(HostSystemServices *instance);
|
||||||
static HostSystemServices *GetInstance();
|
static HostSystemServices *GetInstance();
|
||||||
|
|||||||
@@ -165,6 +165,7 @@
|
|||||||
<ClInclude Include="PLUnalignedPtr.h" />
|
<ClInclude Include="PLUnalignedPtr.h" />
|
||||||
<ClInclude Include="PLWidgets.h" />
|
<ClInclude Include="PLWidgets.h" />
|
||||||
<ClInclude Include="ResolveCachingColor.h" />
|
<ClInclude Include="ResolveCachingColor.h" />
|
||||||
|
<ClInclude Include="WorkerThread.h" />
|
||||||
<ClInclude Include="TextPlacer.h" />
|
<ClInclude Include="TextPlacer.h" />
|
||||||
<ClInclude Include="UTF16.h" />
|
<ClInclude Include="UTF16.h" />
|
||||||
<ClInclude Include="UTF8.h" />
|
<ClInclude Include="UTF8.h" />
|
||||||
@@ -320,6 +321,7 @@
|
|||||||
<ClCompile Include="UTF8.cpp" />
|
<ClCompile Include="UTF8.cpp" />
|
||||||
<ClCompile Include="WindowDef.cpp" />
|
<ClCompile Include="WindowDef.cpp" />
|
||||||
<ClCompile Include="WindowManager.cpp" />
|
<ClCompile Include="WindowManager.cpp" />
|
||||||
|
<ClCompile Include="WorkerThread.cpp" />
|
||||||
<ClCompile Include="XModemCRC.cpp" />
|
<ClCompile Include="XModemCRC.cpp" />
|
||||||
<ClCompile Include="ZipFileProxy.cpp" />
|
<ClCompile Include="ZipFileProxy.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -462,6 +462,9 @@
|
|||||||
<ClInclude Include="FileBrowserUI.h">
|
<ClInclude Include="FileBrowserUI.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="WorkerThread.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="CFileStream.cpp">
|
<ClCompile Include="CFileStream.cpp">
|
||||||
@@ -737,5 +740,8 @@
|
|||||||
<ClCompile Include="FileBrowserUI.cpp">
|
<ClCompile Include="FileBrowserUI.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="WorkerThread.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
152
PortabilityLayer/WorkerThread.cpp
Normal file
152
PortabilityLayer/WorkerThread.cpp
Normal 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;
|
||||||
|
}
|
||||||
23
PortabilityLayer/WorkerThread.h
Normal file
23
PortabilityLayer/WorkerThread.h
Normal 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();
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user