(C++ : IOCP-55) JobQueue - 3

Posted by : at

Category : Cpp   iocp


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에서 다른 객체로 변경될 경우 처리도 곤란하다.

다음강에서 해결해보자


About Taehyung Kim

안녕하세요? 8년차 현업 C++ 개발자 김태형이라고 합니다. 😁 C/C++을 사랑하며 다양한 사람과의 협업을 즐깁니다. ☕ 꾸준한 자기개발을 미덕이라 생각하며 노력중이며, 제가 얻은 지식을 홈페이지에 정리 중입니다. 좀 더 상세한 제 이력서 혹은 Private 프로젝트 접근 권한을 원하신다면 메일주세요. 😎

Star
Useful Links