ShovelingLife
A Game Programmer
ShovelingLife
전체 방문자
오늘
어제
  • 분류 전체보기 (1074)
    • 그래픽스 (57)
      • 공통 (19)
      • 수학 물리 (22)
      • OpenGL & Vulkan (1)
      • DirectX (14)
    • 게임엔진 (183)
      • Unreal (69)
      • Unity (103)
      • Cocos2D-X (3)
      • 개인 플젝 (8)
    • 코딩테스트 (221)
      • 공통 (7)
      • 프로그래머스 (22)
      • 백준 (162)
      • LeetCode (19)
      • HackerRank (2)
      • 코딩테스트 알고리즘 (8)
    • CS (235)
      • 공통 (21)
      • 네트워크 (44)
      • OS & 하드웨어 (55)
      • 자료구조 & 알고리즘 (98)
      • 디자인패턴 (6)
      • UML (4)
      • 데이터베이스 (7)
    • 프로그래밍 언어 (349)
      • C++ (168)
      • C# (90)
      • Java (9)
      • Python (33)
      • SQL (30)
      • JavaScript (8)
      • React (7)
    • 그 외 (10)
      • Math (5)
      • 일상 (5)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

  • Source Code 좌측 상단에 복사 버튼 추가 완료
  • 언리얼 엔진 C++ 빌드시간 단축 꿀팁
  • 게임 업계 코딩테스트 관련
  • 1인칭 시점으로 써내려가는 글들

인기 글

태그

  • 유니티
  • 티스토리챌린지
  • c#
  • 문자열
  • 프로그래머스
  • 파이썬
  • 알고리즘
  • C++
  • 오블완
  • 그래픽스
  • string
  • 함수
  • SQL
  • 클래스
  • 포인터
  • C
  • Unity
  • 언리얼
  • 백준
  • 배열

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
ShovelingLife

A Game Programmer

프로그래밍 언어/C++

C++ std::shared_ptr로 thread safe callback 구현하기

2023. 1. 8. 16:20

리소스를 로딩한다거나 어떤 연산을 수행하기 위해 thread를 만들어서 동작시킬 수 있지만 thread가 언제 끝날지 보장할 수 없기 때문에 이것에 대해 방어적인 코딩이 필요하다.

 

예를 들어 리소스를 thread로 로딩하고 로딩이 완료될 때 마다 해당 인스턴스로 callback을 하여 리소스 로딩이 완료되었음을 알려주는 구현이라고 가정하자.

이 인스턴스는 자신이 요청한 thread가 완료될 때 까지 삭제하면 안되지만 thread가 언제 끝날지 보장할 수 없기 때문에 thread가 언제 끝나더라도 동작하도록 구현할 필요가 있다.

unsafe callback with raw pointer

기존 pointer를 사용해서 구현할 경우 아래와 비슷한 흐름을 가지게 될 것이다.

class Character {
public:
	void PrintItems() {
		for each (int item in _items) {
			std::cout << "item : " << item << std::endl;
		}
	}

	void PushItem(int item) {
		_items.push_back(item);
	}

private:
	std::vector<int> _items;
};

void LoadingThread(std::function<void()> callback) {
	Sleep(1000);
	callback();
}

void main() {
	Character* pChar = new Character();
	std::thread* loading;

	pChar->PushItem(1);
	pChar->PushItem(5);
	pChar->PushItem(10);

	auto callback = std::bind(&Character::PrintItems, pChar);

	callback();

	loading = new std::thread(LoadingThread, printItems);

	delete pChar;
	std::cout << "deleted pChar" << std::endl;

	loading->join();
	if (loading) delete loading;
}

위 경우 main에서 호출하는 callback()은 정상 동작한다.

하지만 LoadingThread가 1초 대기 후에 callback을 호출하는 반면 thread를 만들자 마자 바로 pChar를 메모리 해제하기 때문에 1초 후에 thread가 callback을 호출하면 접근 에러가 발생한다.

실제로 로딩중인 캐릭터가 맞아서 죽거나 view에서 벗어나서 지워야 할 경우 위와 같은 상황이 발생할 수 있다.

이는 raw pointer는 가리키고 있는 메모리가 해제되더라도 그것을 인지하지 못한 채 계속 해당 메모리를 가리키기 때문인데, 누군가 해당 메모리를 가리키고 있다면 그 메모리를 해제하지 못하도록 할 필요가 있다.

thread safe callback with smart pointer

void SafePrint(std::weak_ptr<Character> w) {
	auto pChar = w.lock();
	if (pChar) {
		pChar->PrintItems();
	}
}

void main() {
	auto pChar = std::make_shared<Character>();
	std::thread* loading;

	pChar->PushItem(1);
	pChar->PushItem(5);
	pChar->PushItem(10);

	auto callback = std::bind(&SafePrint, std::weak_ptr<Character>(pChar));

	loading = new std::thread(LoadingThread, callback);

	pChar.reset();	// delete pChar

	std::cout << "deleted pChar" << std::endl;

	loading->join();
	if (loading) delete loading;
}

weak_ptr을 lock()으로 shared_ptr로 변환시킬 수 있는데, 이 때 shared_ptr이 가리키는 객체의 ref count가 main함수의 reset()으로 인해 0이 되었기 때문에 이미 메모리에서 해제된 상태이다.

shared_ptr은 메모리에서 해제시키면서 해당 영역을 NULL로 만들어주기 때문에 단순한 조건문으로 실제로 인스턴스가 메모리에 살아있는지 검사할 수 있다. 아직 메모리에 있을 경우 callback을 수행하며 이미 지워진 경우 callback 자체를 무시하도록 해서 안전하게 구현할 수 있다.

 

출처 : c++11 - std::shared_ptr로 thread safe callback 구현하기 (tistory.com)

저작자표시 (새창열림)

'프로그래밍 언어 > C++' 카테고리의 다른 글

[C++] to_string 함수에 대해서, 특정 타입 > 문자열  (0) 2023.07.20
C++ 전처리기로 코드 영역 블록 설정  (0) 2023.03.25
C 조건부 전처리기  (0) 2023.01.03
C++ 클래스 템플릿에 선언된 friend 함수를 외부에 정의하는 방법  (0) 2023.01.03
C/C++ 예외상황에서의 포인터의 동작  (0) 2022.12.17
    '프로그래밍 언어/C++' 카테고리의 다른 글
    • [C++] to_string 함수에 대해서, 특정 타입 > 문자열
    • C++ 전처리기로 코드 영역 블록 설정
    • C 조건부 전처리기
    • C++ 클래스 템플릿에 선언된 friend 함수를 외부에 정의하는 방법
    ShovelingLife
    ShovelingLife
    Main skill stack => Unity C# / Unreal C++ Studying Front / BackEnd, Java Python

    티스토리툴바