Functor를 이용하지말고 람다를 이용하는 방식도 존재한다.
#include <functional>
int main()
{
PlayerRef player = make_shared<Player>();
std::function<void()> func = [=]()
{
GRoom.Enter(player);
};
// ...
// Job을 이렇게 람다를 이용하여 처리하고 싶음.
func();
}
매개변수를 임시로 보관하는건 어떻게 처리??
#include <functional>
void HellWorld(int32 a, int32 b)
{
std::cout << "hello" << a << b << endl;
}
int main()
{
PlayerRef player = make_shared<Player>();
std::function<void()> func = [=]()
{
// 오히려 더 쉬움
HellWorld(10, 20);
GRoom.Enter(player);
};
// ...
func();
}
- 주의해야 할 점이 몇가지 있다.
- Job을 Push, Flush로 동작하는데 Job을 넣을 Queue를 관리할 것.
PlayerRef player = make_shared<Player>();
의 생명주기를 Job이 실행되는 시점까지 유지해 줄것.(크래쉬 날 수 있음)
위 주의사항을 주의하면서 람다기반의 Job을 구현해보자
- 참고로 함수내부의 람다식을 사용할때 아래와 같이 구현하면 좋다
class Knight : public enable_shared_from_this<Knight>
{
public:
void HealMe(int32 value)
{
_hp += value;
cout << "Heal Me" << endl;
}
void Test()
{
// shared_from_this()를 사용할경우 카운트가 1올라가서 관리됨.
auto job = [self = shared_from_this()]()
{
self->HealMe(self->_hp);
}
}
private:
int32 _hp = 100;
}
구현해보자
#include <functional>
using CallbackType = std::function<void()>;
class Job
{
public:
Job(CallbackType&& callback) : _callback(std::move(callback))
{
}
template<typename T, typename Ret, typename... Args>
Job(shared_ptr<T> owner, Ret(T::* memFunc)(Args...), Args&&... args)
{
_callback = [owner, memFunc, args...]()
{
(owner.get()->*memFunc)(args...);
};
}
void Execute()
{
_callback();
}
private:
CallbackType _callback;
};
class JobSerializer : public enable_shared_from_this<JobSerializer>
{
public:
void PushJob(CallbackType&& callback)
{
auto job = ObjectPool<Job>::MakeShared(std::move(callback));
_jobQueue.Push(job);
}
template<typename T, typename Ret, typename... Args>
void PushJob(Ret(T::*memFunc)(Args...), Args... args)
{
shared_ptr<T> owner = static_pointer_cast<T>(shared_from_this());
auto job = ObjectPool<Job>::MakeShared(owner, memFunc, std::forward<Args>(args)...);
_jobQueue.Push(job);
}
virtual void FlushJob() abstract;
protected:
JobQueue _jobQueue;
};
이제 모든문제가 해결됐는가?
역시 아직은… Push, Pop의 문제가 남았다
특히 현재는 Flush시에 Main 쓰레드를 잡고 아래처럼 동작중인데
int main()
{
// ...
while(true)
{
GRoom->FlushJob();
this_thread::sleep_for(1ms);
}
// ..
}
Room이 여러개로 늘어날 경우도 생기고 이후 Job을 관리 하는 객체가 현재는 Room을 만들어하지만 Room에서 다른 객체로 변경될 경우 처리도 곤란하다.
다음강에서 해결해보자