天天看點

C++20 jthread

vs2019 C++20 jthread

    • 01 jthread的一個實作
    • 02 jthread用法
      • 02.01 cppreference上面的介紹
      • 02.02 可協作中斷的用法
      • 02.03 NICOLAI JOSUTTIS提供了大量測試用例

jthread

是有自動合并和取消支援的

std::thread

jthread

包裝了一下

thread

,提供了線程運作中停止的接口。

jthread

定義在

<thread>

頭檔案中。

使用取消功能需要用到

std::stop_token

。參考:<stop_token>

建議以後使用thread的都開始使用jthread,不必等到c++20出來。

  1. std::jthread對象銷毀時,會調用join,等待其所表示的執行結束。
  2. 支援外部請求中止(通過get_stop_source、get_stop_token和request_stop)。

    std::jthread為了實作上述新功能,帶來了額外的性能開銷(主要是多了一個成員變量)。而根據C++一直以來“不為不使用的功能付費”的設計哲學,他們自然就把這些新功能拆出來新做了一個類。1

01 jthread的一個實作

NICOLAI JOSUTTIS [尼古拉·喬蘇蒂斯]2關于jthread的一個實作:

https://github.com/josuttis/jthread

這個實作沒有使用C++20的新特性。隻有

jthread.hpp

stop_token.hpp

兩個檔案,700多行代碼。

https://github.com/josuttis/jthread/blob/master/source/jthread.hpp

https://github.com/josuttis/jthread/blob/master/source/stop_token.hpp

02 jthread用法

文中所有提到的代碼,整理在:https://github.com/5455945/cpp_demo/tree/master/C%2B%2B20/jthread

02.01 cppreference上面的介紹

jthread在基本用法上面完全相容thread。

https://zh.cppreference.com/w/cpp/thread/jthread/jthread

// https://zh.cppreference.com/w/cpp/thread/jthread/jthread
#include <iostream>
#include <utility>
#include <thread>
#include <chrono>
#include "jthread.hpp" // https://github.com/josuttis/jthread/tree/master/source

void f1(int n)
{
    for (int i = 0; i < 5; ++i) {
        std::cout << "Thread 1 executing\n";
        ++n;
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

void f2(int& n)
{
    for (int i = 0; i < 5; ++i) {
        std::cout << "Thread 2 executing\n";
        ++n;
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

class foo
{
public:
    void bar()
    {
        for (int i = 0; i < 5; ++i) {
            std::cout << "Thread 3 executing\n";
            ++n;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
    int n = 0;
};

class baz
{
public:
    void operator()()
    {
        for (int i = 0; i < 5; ++i) {
            std::cout << "Thread 4 executing\n";
            ++n;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
    int n = 0;
};

void test_jthread_cppreference01()
{
    int n = 0;
    foo f;
    baz b;
    std::jthread t0; // t0 不是線程
    std::jthread t1(f1, n + 1); // 按值傳遞
    std::jthread t2a(f2, std::ref(n)); // 按引用傳遞
    std::jthread t2b(std::move(t2a)); // t2b 現在運作 f2() 。 t2a 不再是線程
    std::jthread t3(&foo::bar, &f); // t3 在對象 f 上運作 foo::bar()
    std::jthread t4(b); // t4 在對象 b 上運作 baz::operator()
    t1.join();
    t2b.join();
    t3.join();
    std::cout << "Final value of n is " << n << '\n';
    std::cout << "Final value of foo::n is " << f.n << '\n';
    // t4 在析構時結合
}
           

02.02 可協作中斷的用法

參考 C ++ 20中的新線程(jthread)功能

使用

request_stop()

jthread

線程發送停止線程請求;在

jthread

線程中使用

stop_requested()

來判斷是否收到停止線程請求。如果收到停止請求,即做出退出線程反應。

void sleep(const int seconds) {
	std::this_thread::sleep_for(std::chrono::seconds(seconds));
}

void test_jthread03() {
	std::jthread jt{ [](std::stop_token st) {
		while (!st.stop_requested()) { // 有停止線程請求的處理
			std::cout << "Doing work\n";
			sleep(1);
		}
	} };
	sleep(5);
	jt.request_stop(); // 請求線程停止,因有響應停止請求而終止線程
	jt.join();
}
           

02.03 NICOLAI JOSUTTIS提供了大量測試用例

https://github.com/josuttis/jthread/tree/master/source中提供了大量測試用例,對了解jthread的用法很有幫助。

  1. std::jthread與std::thread的差別是什麼? ↩︎
  2. 《C++标準庫(第2版)》、《C ++ 17 –完整指南》作者 ↩︎

繼續閱讀