Skip to content

Instantly share code, notes, and snippets.

@badforlabor
Created April 4, 2019 10:18
Show Gist options
  • Select an option

  • Save badforlabor/080216969b73ab3315290e732bd8f49d to your computer and use it in GitHub Desktop.

Select an option

Save badforlabor/080216969b73ab3315290e732bd8f49d to your computer and use it in GitHub Desktop.
ThreadFactory.h
#pragma once;
#include "Core.h"
class ICanExitRunnable : public FRunnable
{
public:
virtual void WaitExit() = 0;
};
template<class T>
class TThreadFactory : public ICanExitRunnable
{
typedef T Type;
friend T;
T Worker;
private:
FRunnableThread* Thread;
FThreadSafeCounter StopTaskCounter;
bool bDone;
public:
template<class ...Types>
TThreadFactory(Types&& ...args) : Worker(Forward<Types>(args)...)
{
StopTaskCounter.Reset();
Thread = FRunnableThread::Create(this, TEXT("ThreadFactory"));
bDone = false;
}
~TThreadFactory()
{
WaitExit();
}
T& Get()
{
return Worker;
}
virtual uint32 Run() override
{
Worker.Before();
while (StopTaskCounter.GetValue() == 0)
{
Worker.Loop();
}
Worker.Done();
bDone = true;
return 1;
}
virtual void WaitExit() override
{
if (Thread == NULL)
{
return;
}
StopTaskCounter.Increment();
while (!bDone)
{
FPlatformProcess::Sleep(0.03f);
}
delete Thread;
Thread = NULL;
}
};
// 如果不是带loop,纯是后台执行的
// 那么不能由主线程销毁,销毁由自定义的Mgr控制。
template<class T>
class TNonBlockWorkFactory : public ICanExitRunnable
{
friend T;
T Worker;
private:
FRunnableThread* Thread;
bool bDone;
public:
template<class ...InArgTypes>
TNonBlockWorkFactory(InArgTypes&& ...args) : Worker(Forward<InArgTypes>(args)...)
{
Thread = FRunnableThread::Create(this, TEXT("ThreadFactory"));
bDone = false;
}
~TNonBlockWorkFactory()
{
WaitExit();
}
T& Get()
{
return Worker;
}
T* MyGetPtr()
{
return &Worker;
}
virtual uint32 Run() override
{
Worker.Run();
bDone = true;
return 1;
}
virtual void WaitExit() override
{
if (Thread == NULL)
{
return;
}
while (!bDone)
{
FPlatformProcess::Sleep(0.03f);
}
delete Thread;
Thread = NULL;
}
};
class FThreadFactory
{
public:
static FThreadFactory& Singleton();
template<class T, typename ...InArgTypes>
static T* CreateNonblock(InArgTypes&& ...Args)
{
auto ptr = new TNonBlockWorkFactory<T>(Forward<InArgTypes>(Args)...);
ICanExitRunnable* p1 = ptr;
Singleton().Nonblocks.Add(TSharedPtr<ICanExitRunnable>(p1));
return ptr->MyGetPtr();
}
template<class T, typename ...InArgTypes>
static TSharedPtr<TNonBlockWorkFactory<T>> CreateNonblock2(InArgTypes&& ...Args)
{
auto p1 = new TNonBlockWorkFactory<T>(Forward<InArgTypes>(Args)...);
auto ptr = TSharedPtr<TNonBlockWorkFactory<T>>(p1);
Singleton().Nonblocks.Add(ptr);
return ptr;
}
template<class T, typename ...InTypes>
static TSharedPtr<TThreadFactory<T>> CreateLoopThread(InTypes&& ...Args)
{
auto p1 = new TThreadFactory<T>(Forward<InTypes>(Args)...);
TSharedPtr<TThreadFactory<T>> ptr = TSharedPtr<TThreadFactory<T>>(p1);
FThreadFactory::Singleton().Loops.Add(ptr);
return ptr;
}
static void Test();
private:
static FThreadFactory* Inst;
TArray<TSharedPtr<ICanExitRunnable>> Nonblocks;
TArray<TSharedPtr<ICanExitRunnable>> Loops;
FThreadFactory();
void OnPreExit();
void EndPIE(bool bIsSimulating);
void StopAndWaitAllThread();
};
class FNonBlockWorkExample
{
public:
FNonBlockWorkExample(int a, float b);
void Run();
};
class FThreadWorkerExample
{
public:
FThreadWorkerExample();
FThreadWorkerExample(int i1, float f2);
void Before();
void Loop();
void Done();
public:
void AddSomething();
public:
static void Test();
};
#include "ThreadFactory.h"
#if WITH_EDITOR
#include "Editor.h"
#endif
FThreadFactory* FThreadFactory::Inst = NULL;
FThreadFactory& FThreadFactory::Singleton()
{
if (Inst == NULL)
{
Inst = new FThreadFactory();
}
return *Inst;
}
void FThreadFactory::Test()
{
auto ptr = CreateNonblock<FNonBlockWorkExample>(1, 2);
auto ptr2 = CreateNonblock2<FNonBlockWorkExample>(1, 2);
}
FThreadFactory::FThreadFactory()
{
#if WITH_EDITOR
if (GIsEditor)
{
FEditorDelegates::EndPIE.AddRaw(this, &FThreadFactory::EndPIE);
}
#endif
FCoreDelegates::OnPreExit.AddRaw(this, &FThreadFactory::OnPreExit);
}
void FThreadFactory::OnPreExit()
{
StopAndWaitAllThread();
}
void FThreadFactory::EndPIE(bool bIsSimulating)
{
StopAndWaitAllThread();
}
void FThreadFactory::StopAndWaitAllThread()
{
for (auto one : Nonblocks)
{
one->WaitExit();
}
for (auto one : Loops)
{
one->WaitExit();
}
}
FNonBlockWorkExample::FNonBlockWorkExample(int a, float b)
{
}
void FNonBlockWorkExample::Run()
{
}
FThreadWorkerExample::FThreadWorkerExample()
{
}
FThreadWorkerExample::FThreadWorkerExample(int i1, float f2)
{
}
void FThreadWorkerExample::Before()
{
}
void FThreadWorkerExample::Loop()
{
}
void FThreadWorkerExample::Done()
{
}
void FThreadWorkerExample::Test()
{
//auto a = FThreadFactory::CreateLoopThread<FThreadWorkerExample>();
auto b = FThreadFactory::CreateLoopThread<FThreadWorkerExample>(1, 2);
b->Get().AddSomething();
b->Get().AddSomething();
b->WaitExit();
}
void FThreadWorkerExample::AddSomething()
{
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment