Search
Duplicate

로딩 씬 (쓰레드, 뮤텍스) 만들기

3D Data는 용량이 매우크고 데이터의 크기가 작지 않다.
그래서 로드를 하는 동안 프로그램을 종료되지 않고 돌아가게 하기 위해서 로딩 쓰레드를 생성하여 프로그램을 실행시킨다. 하지만 이작업에는 큰 단점이 존재한다.
다양한 쓰레드에서 공유자원을 접근해 값을 변경, 읽는 작업을 수행한다면 실제로는 같은 순간에 수행되는것이 아니기 때문에 자신이 원했던 값이 아닌 올바르지 않은 값을 읽어 올 수도 있게 됩니다.
이러한 경쟁 상태(race condition)를 발생시키지 않도록 하기 위해서 C++에서는 mutex라는 객체를 지원합니다.
mutex는 여러 스레드의 공유자원에 대한 동시 접근을 막아 주는 역할을 합니다. C++에서는 많은 종류의 mutex를 지원합니다.
std::mutex(C++11)
std::recursive_mutex(C++11)
std::timed_mutex(C++11)
std::recursive_timed_mutex(C++11)
std::shared_timed_mutex(C++14)
std::shared_mutex(C++17)
모두 공유자원의 동시접근을 막아주는 역할을 하지만 차이점이 존재합니다. 모두 "<mutex>"헤더에 포합되어 있으며 주로 위에서 두가지의 뮤텍스를 사용합니다.
std::mutex는 같은 mutex 객체로 여러 번 잠그면 데드락(deadlock) 현상이 발생합니다.
그래서 std::system_error를 던져주게 됩니다. 하지만 std::recursive_mutex는 같은 객체로 여러번 잠글수 있으며, 이 때에는 잠근 횟수 만큼 다시 unlock을 해 주어야 합니다.
std::timed_mutex는 try_lock_for() 과 try_lock_until()등의 메소드를 이용해서 일정시간, 지정한 시각까지 대기를 할 수 있는 기능을 가지고 있습니다.
C++14에서 추가된 std::shared_timed_mutex는 베타적 잠금 외에 한가지 접근가능한 기능을 통해 2가지의 접근 조건을 가질 수 있습니다. 하나의 쓰레드만 접근 가능하도록 막는 exclusive 상태와 몇개의 쓰레드가 동시에 접근 가능한 shared 상태가 존재합니다.
C++17에서 추가된 std::shared_mutex는 C++14의 std::shared_timed_mutex과 동일한 역할을 하지만 시간과 관련된 메소드가 빠진 클래스라고 볼 수 있습니다. 하지만 내부적으로 condition_variable로 구현된 std::shared_timed_mutex에 비해 Slim Reader Writer Lock (SRW Lock)로 구현된 std::shared_mutex가 훨씬 빠르고 높은 성능을 보여줍니다.
우리 엔진에서는 로딩씬 초기화 부분에서 로딩을 위한쓰레드를 생성해주고 있다.
그리고 쓰레드 로딩이 끝난후 로딩의 끝맺음을 알리기위한 불변수를 하나 넣어주었다.
로딩씬에서는 원래 뮤텍스를 이용해서 락(lock)임계영역을 만들 필요가 없지만 위 에있는 뮤텍스는
여러분들의 학습목적으로 넣어둔 코드이다.
임계영역이 설정되면 저 구간에서는 다른쓰레드는 작업이 멈춘후 대기를 하면서 기다리게 된다.
로딩이 완료된후 main쓰레드에서 나온 자식쓰레드를 다시 부모쓰레드로 넣어주거나
또는 아예 독립적인 쓰레드로 분리시킬수 있다. 둘중에 하나는 꼭 해줘야한다. 자식쓰레드가 남았는데 메인쓰레드가 먼저 종료되면 크러시가 일어나기 떄문이다. 그리고 다른씬으로 이동하면된다.
이제는 로딩을 다른쓰레드를 이용해서 진행하게 된다.