SW 그리고 아빠 엔지니어링 중...

아는 만큼 보이고, 경험해봐야 알 수 있고, 자꾸 써야 내 것이 된다.

L C++/Concurrency

[Concurrency] this_thread 특징

보리남편 김 주부 2023. 7. 11. 20:56
this_thread 함수 특징에 대해 정리하고자 한다.

 

std::thread::id 특징


1. std::this_thread::id를 화면에 출력하면 정수로 표현되지만 실제는 정수 타입이 아니며 변환도 안된다.

//특징 1
int n = tid1; // error. 

std::thread::id tid1 = std::this_thread::get_id();

 

2. 컨테이너에 보관 가능하고, hash도 가능하다

//2. 컨테이너에 보관 가능하고, hash 도 가능
std::vector< std::thread::id> v; // ok..
std::hash< std::thread::id> h;   // ok

// 특징 3.  == , != 연산 가능합니다.
    tid1 == tid1;

 

3. 연산이 가능하다. (== , != 등)

std::thread::id tid1 = std::this_thread::get_id();

tid1 == tid1;

 

sleep_for, sleep_until : thread를 재우는 함수


sleep_for : 특정 시간 동안
sleep_until : 특정 시간까지

 

thread를 재우는 함수의 시간의 입력은 chrono 라이브러리를 이용해서 입력할 수 있다.

chrono 시간/날짜 관련 C++ 표준 라이브러리
#include <iostream>
#include <thread>
#include <chrono>

time_t toUTC(std::tm& timeinfo)
{
#ifdef _WIN32
    std::time_t tt = _mkgmtime(&timeinfo);
#else
    time_t tt = timegm(&timeinfo);
#endif
    return tt;
}

std::chrono::system_clock::time_point createDateTime(int year, int month, int day, int hour, int minute, int second)
{
    tm timeinfo1 = tm();
    timeinfo1.tm_year = year - 1900;
    timeinfo1.tm_mon = month - 1;
    timeinfo1.tm_mday = day;
    timeinfo1.tm_hour = hour;
    timeinfo1.tm_min = minute;
    timeinfo1.tm_sec = second;
    tm timeinfo = timeinfo1;
    time_t tt = toUTC(timeinfo);
    return std::chrono::system_clock::from_time_t(tt);
}

int main()
{
    // 스레드 재우는 함수 : sleep_for
    std::this_thread::sleep_for(3); // error
    // => 인자는 chrono 라이브러리 형태로 전달해야 한다.
    
    std::chrono::seconds sec(3);
    std::this_thread::sleep_for(sec); // ok
   
    auto t1 = createDateTime(2023, 5, 25, 12, 0, 0); 
    std::this_thread::sleep_until(t1); // std::chrono::system_clock::time_point type
}

 

TIP. literals을 이용해서 아래와 같이 시간을 입력할 수도 있다.

#include <chrono>
using namespace std::literals;

std::this_thread::sleep_for(3us);
std::this_thread::sleep_for(3s); // 이렇게도 사용가능
                        // "user define literal 문법"
                        // 3s 가 결국 std::chrono::seconds 반환

 

yield : 자신의 실행 시간을 포기하는 함수


 

스레드가 자신에게 부여된 실행 시간을 포기(다른 스레드를 실행하라고 하는 것.)

#include <iostream>
#include <chrono>
#include <thread>

// yield 를 사용한 sleep 구현
void little_sleep(std::chrono::microseconds us)
{
    auto target = std::chrono::high_resolution_clock::now() + us;

    // target : 깨어나야 하는 시간
    while (std::chrono::high_resolution_clock::now() < target)
        std::this_thread::yield();
}
 
int main()
{
    auto start = std::chrono::high_resolution_clock::now();
 
    little_sleep(std::chrono::microseconds(100));
 
    auto elapsed = std::chrono::high_resolution_clock::now() - start;
    std::cout << "waited for "
              << std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count()
              << " microseconds\n";
}

결과: 

waited for 102 microseconds
위 예제로 보면 사실 거의 지연시간이 없다.
현재 main thread에서 yield를 했기에 영향이 없지만 다른 thread와 동시에 동작 할 때는 자원을 효율적으로 사용할 수 있는 방법이다.

 

참고


* 본 글에 예제 코드는 코드누리 교육을 받으면서 제공된 샘플코드를 활용하였습니다.

728x90