Thread local의 사용법

다메즈마 (토론 | 기여)님의 2018년 11월 6일 (화) 01:59 판 (새 문서: 분류:C++ 원래 쓰레드 마다 별개의 정보를 기록할 필요가 있는 경우는 그다지 많지 않다만, 필요한 경우가 있다. 예를 들면 공통된 데이...)
(차이) ← 이전 판 | 최신판 (차이) | 다음 판 → (차이)

원래 쓰레드 마다 별개의 정보를 기록할 필요가 있는 경우는 그다지 많지 않다만, 필요한 경우가 있다. 예를 들면 공통된 데이터를 가지고 스레드들이 공유하며 별개의 데이터를 생산해야 할 때 필요하다. 다음 코드는 C++에서 스레드마다 별개의 데이터를 가져야 하는 경우를 보여준다.

#include <iostream>
#include <memory>
#include <mutex>
#include <optional>
class Tokeniser
{
public:
	Tokeniser(const char * str, char pattern):m_str(str), m_pattern(pattern)
	{
		
	}
	std::optional<size_t> Next()
	{
		thread_local static size_t last_index = -1;
		while (m_str[++last_index] != '\0')
		{
			if (m_str[last_index] == m_pattern)
			{
				return std::optional<size_t>(last_index);
			}
			
		}
		return std::nullopt;
	}
	const char* GetStr() const
	{
		return m_str;
	}
private:
	char m_pattern;
	const char * m_str;
};
int main()
{
	Tokeniser tokeniser("1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37", ' ');
	std::thread threads[5];
	std::mutex m;
	for (std::thread& thread : threads)
	{
		thread = std::move(std::thread([&m, &tokeniser]() {
			size_t pre = 0;
			
			for (auto endindex = tokeniser.Next(); endindex.has_value(); endindex = tokeniser.Next())
			{
				m.lock();
				for (size_t i = pre; i < endindex.value(); i++)
				{
					std::cout << tokeniser.GetStr()[i];
				}
				
				m.unlock();
				std::cout << std::endl;
				pre = endindex.value();
			}
		}));
	}
	for (std::thread& thread : threads)
	{
		thread.join();
	}
	return 0;
}

이렇게 스레드마다 별개의 데이터를 가져야 할 때, 외부에서 동적 메모리를 할당하지 않고, 유지할 수 있는 방법을 thread_local 키워드가 제공한다.

windows에서는 C++11이 나오기 전에 TLS라 하여 동일한 개념을 지원했다.