C ++ 20: Geri arama ile bir iş parçacığının kooperatif kesintisi

Adanali

Active member
C ++ 20: Geri arama ile bir iş parçacığının kooperatif kesintisi


  1. C ++ 20: Geri arama ile bir iş parçacığının kooperatif kesintisi

Bir hatırlatma olarak: önceki makalemde “Yazılım Geliştirme: C ++ 20'de bir iş parçacığının işbirliği kesintisi” aşağıdaki programı sundum.








Rainer Grimm yıllardır yazılım mimarı, ekip ve eğitim müdürü olarak çalıştı. C ++ programlama dilleri, Python ve Haskell hakkında makaleler yazmayı seviyor, ancak uzman konferanslarla konuşmayı da seviyor. Modern C ++ blogunda, C ++ tutkusuyla yoğun bir şekilde ilgileniyor.













// invokeCallback.cpp

#include <chrono>&#13;
#include <iostream>&#13;
#include <thread>&#13;
#include <vector>&#13;
&#13;
using namespace::std::literals;&#13;
&#13;
auto func = [](std::stop_token stoken) { // (1)&#13;
int counter{0};&#13;
auto thread_id = std::this_thread::get_id();&#13;
std::stop_callback callBack(stoken, &#13;
[&counter, thread_id] { // (2)&#13;
std::cout << "Thread id: " << thread_id &#13;
<< "; counter: " << counter << 'n';&#13;
});&#13;
while (counter < 10) {&#13;
std::this_thread::sleep_for(0.2s);&#13;
++counter;&#13;
}&#13;
};&#13;
&#13;
int main() {&#13;
&#13;
std::cout << 'n';&#13;
&#13;
std::vector<std::jthread> vecThreads(10);&#13;
for(auto& thr: vecThreads) thr = std::jthread(func);&#13;
&#13;
std::this_thread::sleep_for(1s); // (3)&#13;
&#13;
for(auto& thr: vecThreads) thr.request_stop(); // (4)&#13;
&#13;
std::cout << 'n';&#13;
&#13;
}


On iş parçacığının her biri lambda işlevini çağırıyor func (1) Hon. Geri arama (2) kimlik iş parçacığını ve sayaçını gösterir. Ana iş parçacığı (3) bir saniye ve alt iplikler uyuduğundan, 4 sayaç geri çağrıların çağrıldığı zamandır. Arama thr.request_stop() Deralark her iş parçacığındaki geri çağrıda.








Son makalemde bir soru cevaplanmadı:

Geri arama nerede gerçekleştirildi?


. std::stop_callback-Codor, geri arama işlevini kaydeder. std::stop_tokenBu iştirak aracılığıyla std::stop_source Verilir. Bu geri arama işlevi, request_stop() arayın veya iş parçacığında std::stop_callback inşa edildi. Tutuklama talebi kaydetmeden önce std::stop_callback Geri arama, iş parçacığında çağrılırsa std::stop_callback inşa edildi. Aksi takdirde geri arama, iş parçacığında çağrılır, request_stop çağrılar. Çağrı çağrılırsa request_stop() İpliği gerçekleştirdikten sonra, std::stop_callback Yapılan, kaydedilen geri arama asla çağrılmaz.

Aynı ile bir veya daha fazla iş parçacığı için birden fazla geri arama yapabilirsiniz std::stop_token kayıt olmak. C ++ standardı, gerçekleştirildikleri sipariş için herhangi bir garanti sunmaz.

Bir Geri Aramadan Daha Fazlası



// invokeCallbacks.cpp&#13;
&#13;
#include <chrono>&#13;
#include <iostream>&#13;
#include <thread>&#13;
&#13;
using namespace std::literals;&#13;
&#13;
void func(std::stop_token stopToken) {&#13;
std::this_thread::sleep_for(100ms);&#13;
for (int i = 0; i <= 9; ++i) {&#13;
std::stop_callback cb(stopToken, { std::cout << i; });&#13;
}&#13;
std::cout << 'n';&#13;
}&#13;
&#13;
int main() {&#13;
&#13;
std::cout << 'n';&#13;
&#13;
std::jthread thr1 = std::jthread(func);&#13;
std::jthread thr2 = std::jthread(func);&#13;
thr1.request_stop();&#13;
thr2.request_stop();&#13;
&#13;
std::cout << 'n';&#13;
&#13;
}










Sinyal göndermek için genel bir mekanizma



Çift std::stop_source VE std::stop_token Bir sinyal göndermek için genel bir mekanizma olarak görülebilir. Birinden std::stop_token Kopyalı, sinyali bir şey yapan herhangi bir varlığa gönderebilirsiniz. Aşağıdaki örnekte kullanıyorum std::async, std::promise, std::thread VE std::jthread farklı kombinasyonlarda.


// signalStopRequests.cpp&#13;
&#13;
#include <iostream>&#13;
#include <thread>&#13;
#include <future>&#13;
&#13;
using namespace std::literals;&#13;
&#13;
void function1(std::stop_token stopToken, const std::string& str){&#13;
std::this_thread::sleep_for(1s);&#13;
if (stopToken.stop_requested()) std::cout << str &#13;
<< ": Stop requestedn";&#13;
}&#13;
&#13;
void function2(std::promise<void> prom, &#13;
std::stop_token stopToken, const std::string& str) {&#13;
std::this_thread::sleep_for(1s);&#13;
std::stop_callback callBack(stopToken, [&str] { &#13;
std::cout << str << ": Stop requestedn"; &#13;
});&#13;
prom.set_value();&#13;
}&#13;
&#13;
int main() {&#13;
&#13;
std::cout << 'n';&#13;
&#13;
std::stop_source stopSource; // (1)&#13;
&#13;
std::stop_token stopToken = &#13;
std::stop_token(stopSource.get_token()); // (2)&#13;
&#13;
std::thread thr1 = &#13;
std::thread(function1, stopToken, "std::thread"); // (3)&#13;
&#13;
std::jthread jthr = &#13;
std::jthread(function1, stopToken, "std::jthread"); // (4)&#13;
&#13;
auto fut1 = std::async([stopToken] { // (5)&#13;
std::this_thread::sleep_for(1s);&#13;
if (stopToken.stop_requested()) std::cout &#13;
<< "std::async: Stop requestedn";&#13;
});&#13;
&#13;
std::promise<void> prom; // (6)&#13;
auto fut2 = prom.get_future();&#13;
std::thread thr2(function2, std::move(prom), &#13;
stopToken, "std::promise");&#13;
&#13;
stopSource.request_stop(); // (7)&#13;
if (stopToken.stop_requested()) &#13;
std::cout << "main: Stop requestedn"; // (8)&#13;
&#13;
thr1.join();&#13;
thr2.join();&#13;
&#13;
std::cout << 'n';&#13;
&#13;
}&#13;



Sayesinde stopSource (1) Yapabilirim stopToken (2) Her mevcut varlık için kullanım, ör. B. std::thread (3), std :: jthread (4), std :: async (5) veya std::promise (6). A std::stop_token Kopyalamak ucuz. (7) Çöz stopSource.request_stop dışında. Ana iş parçacığı (8) ayrıca sinyali alır. Bu örnekte kullanın std::jthread. std::jthread VE std::condition_variable_any Kooperatif kesintilerle daha uygun bir şekilde karşılaşabilmek için üyelerin açık işlevleri vardır. Diğer “C ++ 20 ile geliştirilmiş bir iş parçacığı” makalesinde.

Sırada ne var?


Önümüzdeki iki hafta içinde yazmayı ara vereceğim. Bu yüzden C ++ 23'e geri döneceğim ve ilk kez 26 ekleyeceğim.


(RME)
 
Üst