일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- vector size
- operator overloading
- placement new
- this call
- conversion constructor
- base from member
- new&delete
- std::endl
- virtual destructor
- std::ostream
- C++
- discord bot
- virtual function
- member function pointer
- diamond inheritance
- pointer to member data
- increment operator
- c++ multi chatting room
- suffix return type
- std::vector
- virtual inheritance
- vector capacity
- std::cout
- virtual function table
- return by reference
- constructor
- c++ basic practice
- 더 지니어스 양면포커
- delete function
- dynamic_cast
- Today
- Total
I'm FanJae.
[C++ Concurrent] std::this_thread, std::chrono 본문
1. std::this_thread namespace
- 스레드 관련 4개의 함수를 제공하는 namespace
- <thread> 헤더
std::this_thread::get_id() | 현재 스레드의 ID 반환 |
std::this_thread::sleep_for() | 주어진 시간 만큼 현재 스레드 재우기 |
std::this_thread::sleep_until() | 주어진 시간 까지 현재 스레드 재우기 |
std::this_thread::yield() | 다른 스레드를 실행할 수 있도록 힌트 제공 |
1-1. std::this_thread::get_id()
- 실행중인 현재 스레드의 ID를 반환한다.
std::thread_id get_id() noexcept;
#include <iostream>
#include <thread>
int main()
{
std::cout << std::this_thread::get_id() << std::endl;
std::thread::id tid1 = std::this_thread::get_id();
std::thread::id tid2 = std::this_thread::get_id();
tid1 == tid2;
tid1 < tid2;
std::hash<std::thread::id> h;
std::cout << h(td1) << std::endl;
}
① std::thread::id
- 스레드 ID를 나타내는 가벼운 구조체
- cout로 출력 가능하고 비교 연산도 가능하다.
- 정수로 변환이 안된다.
- std::hash<std::thread::id> 함수 객체가 제공되므로 unordered 컨테이너에 키 값으로 사용가능하다.
1-2. sleep_for(), sleep_until()
sleep_for() | 주어진 시간 만큼 현재 스레드 멈추기(재우기) |
sleep_until() | 주어진 시간 까지 현재 스레드 멈추기(재우기) |
template <class Rep, class Period >
void sleep_for ( const std::chrono::duration<Rep, Period>& sleep_duration);
template <class Rep, class Duration >
void sleep_until ( const std::chrono::time_point<Clock, Duration>& sleep_time);
- 위와 같은 형태이다.
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::literals;
int main()
{
std::this_thread::sleep_for(std::chronno::seconds(3));
std::this_thread::sleep_for(3s); // 3ms, 3ns, 3min
// std::this_thread::sleep_for(3); // error
std::chrono::time_point tp1 = std::chrono::steady_clock::now();
std::this_thread::sleep_until( tp1 + 2000ms);
}
- sleep_for를 사용할 때는 단순 숫자만 넘기면 std::chrono 형태가 아니기 때문에 오류가 발생한다.
- sleep_until은 특정 시간을 구해서 사용할 수 있다.
1-3. std::this_thread::yield()
- 다른 스레드에 실행 흐름을 양보할때 사용한다.
#include <iostream>
#include <chrono>
#include <thread>
using namespace std::literals;
void mysleep(std::chrono::microseconds us) // micro 단위 초 인자.
{
auto target = std::chrono::high_resolution_clock::now() + us;
// 현재 시간 구한 이후 10ms을 더함.
while (std::chrono::high_resolution_clock::now() < target)
{
std::this_thread::yield(); // 실행 흐름을 다른 스레드에게 양보.
}
// 주기적으로 깨어나서 시간을 체크하고 목표시간이 안되면 계속 양보함.
}
int main()
{
mysleep(1s);
}
2. chrono
2-1. chrono 라이브러리
- 시간을 다루는 C++ 표준 라이브러리이다.
- <chrono> 헤더
- std::chrono namespace 사용한다.
#include <iostream>
#include <chrono>
#include <thread>
int main()
{
std::chrono::hours h(10);
std::chrono::minutes m(10);
std::chrono::seconds s1(10);
std::chrono::milliseconds s2(10);
std::chrono::nanoseconds s3(10);
std::cout << s1.count() << std::endl;
std::chrono::duration<long long> d1(10);
}
※ chrono 라이브러리의 모든 시간 타입은 duration<>의 alias이다.
using nanoseconds = duration<long long, nano>;
using microseconds = duration<long long, micro>;
using milliseconds = duration<long long, milli>;
using seconds = duration<long long>;
using minutes = duration<int, ratio<60>>;
using hours = duration<int, ratio<3600>>;
- sleep_for를 보면, alias가 아닌 실제로는 chrono::duration으로 되어 있음을 확인할 수 있다.
- 이외에도 chrono 용 user define literal이 존재한다. 10s, 10ms, 10ns, 10min, 10h 등이 존재한다.
- using namespace std::literals
※ 이와 같은 이유로 sleep_for()를 사용하는 방법은 크게 3가지라고 볼 수 있다.
std::this_thread::sleep_for( std::chrono::seconds(3) );
std::this_thread::sleep_for( 3s );
std::this_thread::sleep_for( std::chrono::duration<long, long>(3) );
2-2. time_point
- 앞서 sleep_until() 함수의 경우는 std::chrono::time_point를 사용했다.
#include <iostream>
#include <chrono>
#include <thread>
using namespace std::literals;
int main()
{
std::chrono::time_point tp1 = std::chrono::system_clock::now();
std::chrono::hours h = std::chrono::duration_cast<std::chrono::hours>(tp1.time_since_epoch()); // 1970년 1월 1일을 기준으로 몇시간이 지났는가?
std::this_thread::sleep_for(3ms);
std::this_thread::sleep_until(std::chrono::system_clock::now() + 200ms);
}
duration | 값과 단위, 3(30, 1) -> 30초(seconds) (30, 1/1000) -> 30 밀리초 using seconds = duration<long long, ratio<1, 1>>; using millseconds = duration<long long, ratio<1, 1000>>; |
time_point | 기준 시간 + duration epoch time : 1970년 1월 1일 + duration |
- duration은 특정한 값과 단위가 존재하지만, time_point는 duration에 기준 시간이 존재한다.