STL thread의 목적
기존에 OS별 별도로 돌던 thead를 하나로 합쳐보자!
 단, C++표준이기에 모든 OS에서 돌아가게 만들었다.
 그에 따른 쓰기 불편한 점이 몇 가지 존재한다..
기존의 Thread 정리
얼마나 불편했는지 보자
// Windwos
#include <Windows.h>
DWORD WINAPI PrintMessage()
{
    // ...
}
int main() {
    DWORD myThreadID;
    HANDLE myHandle = CreateThread(0, 0, PrintMessage, NULL, 0, &myThreadID);
    WaitForSingleObject(myHandle, INFINITE);
    // thread가 종료될때 까지 기다린다.
    CloseHandle(myHandle);
    return 0;
}
// POSIX(pthread)
#include <pthread.h>
void *printMessage()
{
    // ...
}
int main() {
    pthread_t thread = 0;
    int result_code = pthread_create(&thread, NULL, printMessage, NULL);
    result_code = pthread_join(thread, NULL);
    return 0;
}
사용자는 이걸 다 알아야 한다.
C++11 전까지 표준 멀티쓰레딩 라이브러리가 없음
 OS마다 멀티쓰레딩 구현이 달랐음
- 리눅스/유닉스 : POSIX(pthread)
 - 윈도우 쓰레드 - 윈도우에서 pthread를 사용할순 있음(ver 1003.1만) - 불편하네… 표준 Thread를 만들어 보자
 
thread 생성
#include <iostream>
#include <string>
#include <thread>
void PrintMessage(const std::string& message)
{
    std::cout << message << std::endl;
}
int main() {
    std::thread thread(PrintMessage, "Message from a child thread");
    
    PrintMessage("Waiting the child thread");
    // 현재 스레드에서 떼어 내기
    thread.detach();
    // 다시 붙이고 싶다면?
    if(thread.joinable())
    {
        thread.join();
    }
    return 0;
}
// 람다식 사용
#include <iostream>
#include <string>
#include <thread>
int main() {
    auto PrintMessage = [](const std::string& message)
    {
        std::cout << message << std::endl;
    };
    std::thread thread(PrintMessage, "Message from a child thread");
    
    PrintMessage("Waiting the child thread");
    thread.join();
    return 0;
}
// 람다식 스레드에 매개변수 넣기
#include <iostream>
#include <string>
#include <thread>
#include <vector>
int main() {
    std::vector<int> list(100, 1);
    int result = 0;
    std::thread thread([](const std::vector<int>& v, int& result)
    {
        for( auto item : v )
        {
            result += item;
        }
    }, list, std::ref(result));
    thread.join();
    std::cout << "Result: " << result << std::endl;
    return 0;
}
thread에 매개변수 넣기
#include <iostream>
#include <thread>
using namespace std;
void f1(int a, int b)
{
}
int main()
{
    thread t1(&f1, 1, 2);
    thread t2(bind(&f1, 1, 2));
    // 둘 다 동일한 표현이다.
    t1.join();
    t2.join();
}
int n = 10;
thread t1(&f1, 1, n);            // error
thread t1(&f1, 1, ref(n));       // ok
// thread 잠깐 정지
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
int main()
{
    thread::id id = this_thread::get_id();
    cout << id << endl;
    this_thread::sleep_for(3s);
    this_thread::sleep_until(chrono::system_clock::now()+3s);
    this_thread::yield();           // 다른 스레드에게 우선순위를 양보한다.
}
#include <iostream>
#include <thread>
using namespace std;
void foo()
{
    cout << "thread start" << endl;
    this_thread::sleep_for(2s);
    cout << "thread end" << endl;
}
int main()
{
    thread t(&foo);
    t.join();       // 스레드 종료를 대기
    // or
    // t.detach();
}
#include <iostream>
#include <thread>
using namespace std;
void f1() {}
void f2(int a) {}
struct Worker
{
    void Main() {}
};
struct Functor
{
    void operator()() {}
};
int main()
{
    thread t1(&f1);
    thread t2(&f2, 5);
    Worker w;
    thread t3(&Workder::Main, &w);
    Functor f;
    thread t4(f);
    thread t5([](){cout << "thread t5" << endl;});
}