ไลบรารี QCoro จัดเตรียมชุดเครื่องมือเพื่อใช้ C++20 coroutines กับ Qt
ดูตัวอย่างด้านล่างเพื่อดูว่า Coroutines คืออะไร:
QNetworkAccessManager networkAccessManager;// co_await การตอบกลับ - coroutine จะถูกระงับจนกว่า QNetworkReply จะเสร็จสิ้น// ในขณะที่ coroutine ถูกระงับ *การวนซ้ำเหตุการณ์ Qt จะทำงานตามปกติ*.const QNetworkReply *reply = co_await networkAccessManager.get(url); // เมื่อการตอบกลับเสร็จสิ้น โค้ดของคุณจะกลับมาทำงานต่อที่นี่ราวกับว่าไม่มีอะไรน่าอัศจรรย์เกิดขึ้น ;-)const auto data = ตอบกลับ -> อ่านทั้งหมด ();
ต้องใช้คอมไพลเลอร์ที่รองรับ couroutines TS ดูเอกสารประกอบสำหรับรายการคอมไพเลอร์และเวอร์ชันที่รองรับ
เอกสารประกอบ
QCoro จัดเตรียมเครื่องมือที่จำเป็นเพื่อให้ใช้งาน C++20 coroutines กับ Qt ได้อย่างง่ายดาย รากฐานที่สำคัญของไลบรารีคือ QCoro::Task<T>
ซึ่งแสดงถึง Coroutine ที่ถูกดำเนินการและอนุญาตให้ผู้เรียกรอผลลัพธ์ของ Coroutine แบบอะซิงโครนัส นอกจากนี้ QCoro ยังมีชุด wrapper สำหรับประเภท Qt ทั่วไป เช่น QTimer
, QNetworkReply
, QDBusPendingCall
, QFuture
และอื่นๆ ที่อนุญาตให้ co_await
การดำเนินการแบบอะซิงโครนัสโดยตรง
นอกจากนี้ยังมีฟังก์ชัน qCoro()
อันมหัศจรรย์ที่สามารถรวมฟังก์ชันและประเภท Qt ดั้งเดิมจำนวนมากเพื่อให้เป็นมิตรกับโครูทีน
ไปตรวจสอบเอกสารเพื่อดูรายการคุณสมบัติที่รองรับและประเภท Qt ทั้งหมด
QDBusPendingCall
QCoro สามารถรอให้การเรียก D-Bus แบบอะซิงโครนัสเสร็จสิ้นได้ ไม่จำเป็นต้องใช้ QDBusPendingCallWatcher
กับ QCoro - เพียงแค่ co_await
ผลลัพธ์แทน ในขณะที่ co_awaiting ลูปเหตุการณ์ Qt จะทำงานตามปกติ
QDBusInterface remoteServiceInterface{serviceName, objectPath, interface};const QDBusReply<bool> isReady = co_await remoteServiceInterface.asyncCall(QStringLiteral("isReady"));
เอกสารฉบับเต็มได้ที่นี่
QFuture
QFuture แสดงถึงผลลัพธ์ของงานอะซิงโครนัส โดยปกติคุณจะต้องใช้ QFutureWatcher
เพื่อรับการแจ้งเตือนเมื่ออนาคตพร้อม ด้วย QCoro คุณสามารถ co_await
ได้เลย!
const QFuture<int> Task1 = QtConcurrent::run(....);const QFuture<int> Task2 = QtConcurrent::run(....);const int a = co_await ภารกิจ 1; const int b = co_await ภารกิจ 2; co_return a + b;
เอกสารฉบับเต็มได้ที่นี่
QNetworkReply
การดำเนินการร้องขอเครือข่ายด้วย Qt อาจเป็นเรื่องที่น่าเบื่อ - วิธีสัญญาณ / สล็อตขัดขวางการไหลของโค้ดของคุณ คำขอเชื่อมโยงและการจัดการข้อผิดพลาดกลายเป็นเรื่องวุ่นวายอย่างรวดเร็ว และโค้ดของคุณถูกแบ่งออกเป็นฟังก์ชันต่างๆ มากมาย แต่ไม่ใช่กับ QCoro ที่คุณสามารถ co_await
QNetworkReply
เพื่อเสร็จสิ้น:
QNetworkAccessManager qnam; QNetworkReply *reply = qnam.get(QStringLiteral("https://github.com/qcoro/qcoro"));const auto contents = co_await ตอบกลับ; ตอบกลับ -> ลบLater (); ถ้า (ตอบกลับ -> ข้อผิดพลาด () ! = QNetworkReply :: NoError) {co_return handleError (ตอบกลับ); } const auto link = findLinkInReturnedHtmlCode (เนื้อหา); ตอบกลับ = qnam.get (ลิงก์); const ข้อมูลอัตโนมัติ = co_await ตอบกลับ; ตอบกลับ -> ลบLater (); ถ้า (ตอบกลับ -> ข้อผิดพลาด () ! = QNetworkReply :: NoError) {co_return handleError (ตอบกลับ); - -
เอกสารฉบับเต็มได้ที่นี่
QTimer
บางทีคุณอาจต้องการชะลอการรันโค้ดของคุณสักวินาที บางทีคุณอาจต้องการรันโค้ดบางโค้ดในช่วงเวลาที่ทำซ้ำ สิ่งนี้กลายเป็นเรื่องเล็กน้อยมากด้วย co_await
:
ตัวจับเวลา QTimer; จับเวลา setInterval (1 วินาที); timer.start();for (int i = 1; i <= 100; ++i) {co_await timer;qDebug() << "กำลังรอ" << i << " วินาที..."; }qDebug() << "เสร็จสิ้น!";
เอกสารฉบับเต็มได้ที่นี่
QIODevice
QIODevice
เป็นคลาสพื้นฐานสำหรับหลายคลาสใน Qt ที่อนุญาตให้เขียนและอ่านข้อมูลแบบอะซิงโครนัสได้ คุณจะทราบได้อย่างไรว่ามีข้อมูลพร้อมที่จะอ่าน? คุณสามารถเชื่อมต่อกับ QIODevice::readyRead()
singal หรือคุณสามารถใช้ QCoro และ co_await
อ็อบเจ็กต์ได้:
socket->write("PING");// กำลังรอ "pong"const auto data = co_await socket;co_return CalculatorLatency(data);
เอกสารฉบับเต็มได้ที่นี่
ไปตรวจสอบเอกสารฉบับเต็มเพื่อเรียนรู้เพิ่มเติม
บางครั้งไม่สามารถใช้ co_await
เพื่อจัดการกับผลลัพธ์ของ coroutine - โดยปกติเมื่อเชื่อมต่อกับโค้ดของบุคคลที่สามที่ไม่รองรับ coroutines ในสถานการณ์เหล่านั้น เป็นไปได้ที่จะเชื่อมโยงการเรียกกลับต่อเนื่องกับ coroutine ซึ่งจะถูกเรียกใช้แบบอะซิงโครนัสเมื่อ coroutine เสร็จสิ้น
เป็นโมฆะ RegularFunction() {someCoroutineReturningInt().then([](int result) {// จัดการผลลัพธ์}); -
การเรียกกลับต่อเนื่องอาจเป็น coroutine และผลลัพธ์ของนิพจน์ทั้งหมดคือ Task โดยที่ T คือประเภทการส่งคืนของการต่อเนื่อง ด้วยเหตุนี้จึงเป็นไปได้ที่จะ co_await
โซ่ทั้งหมดหรือเชื่อมโยงหลาย ๆ .then()
ความต่อเนื่อง
เอกสารฉบับเต็มได้ที่นี่
ตัวสร้างคือโครูทีนที่สร้างค่าหลายค่าอย่างเกียจคร้าน แม้ว่าจะไม่ได้มีอะไรเฉพาะเจาะจงกับ Qt แต่ QCoro ก็มีเครื่องมือที่จำเป็นสำหรับผู้ใช้ในการสร้างตัวสร้างแบบกำหนดเองในแอปพลิเคชัน Qt ของตน
QCoro จัดเตรียม API สำหรับทั้งเครื่องกำเนิดไฟฟ้าแบบซิงโครนัส ( QCoro::Generator<T>
) และเครื่องกำเนิดไฟฟ้าแบบอะซิงโครนัส ( QCoro::AsyncGenerator<T>
) ตัวสร้างทั้งสองตัวมี API ที่เหมือนคอนเทนเนอร์: ฟังก์ชันสมาชิก begin()
และ end()
ที่ส่งคืนออบเจ็กต์ที่เหมือนตัววนซ้ำ ซึ่งเป็น API ที่รู้จักกันดีและเป็นที่ยอมรับ และทำให้ตัวสร้างเข้ากันได้กับอัลกอริธึมที่มีอยู่
QCoro::เครื่องกำเนิดไฟฟ้า<int> ฟีโบนัชชี() { ควินท์64 ก = 0, ข = 0; Q_FOREVER {co_yield b;const อัตโนมัติ tmp = b; ก = ข; ข += ทีพีพี; - } เป็นโมฆะ printFib (สูงสุด quint64) {สำหรับ (fib อัตโนมัติ : fibonacci ()) { ถ้า (fib > สูงสุด) {break; - มาตรฐาน::cout << ปลิ้นปล้อน << std::endl; - -
เอกสารฉบับเต็มได้ที่นี่
MIT License
Copyright (c) 2022 Daniel Vrátil <[email protected]>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.