Pustaka QCoro menyediakan seperangkat alat untuk menggunakan coroutine C++20 dengan Qt.
Lihatlah contoh di bawah ini untuk melihat betapa menakjubkannya coroutine:
QNetworkAccessManager networkAccessManager;// co_await balasan - coroutine ditangguhkan hingga QNetworkReply selesai.// Saat coroutine ditangguhkan, *perulangan peristiwa Qt berjalan seperti biasa*.const QNetworkReply *reply = co_await networkAccessManager.get(url); // Setelah balasan selesai, kode Anda dilanjutkan di sini seolah-olah tidak ada hal menakjubkan yang terjadi ;-)const data otomatis = balasan->readAll();
Ini memerlukan kompiler dengan dukungan untuk couroutine TS, lihat dokumentasi untuk daftar kompiler dan versi yang didukung.
Dokumentasi
QCoro menyediakan alat yang diperlukan untuk memudahkan penggunaan coroutine C++20 dengan Qt. Landasan perpustakaan adalah QCoro::Task<T>
, yang mewakili coroutine yang dieksekusi dan memungkinkan hasil coroutine ditunggu secara asinkron oleh pemanggilnya. Selain itu, QCoro menyediakan satu set pembungkus untuk tipe Qt umum, seperti QTimer
, QNetworkReply
, QDBusPendingCall
, QFuture
dan lainnya, yang memungkinkan untuk co_await
operasi asinkronnya secara langsung.
Selain itu, ada fungsi ajaib qCoro()
yang dapat menggabungkan banyak fungsi dan tipe Qt asli agar ramah coroutine.
Periksa dokumentasi untuk daftar lengkap semua fitur yang didukung dan tipe Qt.
QDBusPendingCall
QCoro dapat menunggu panggilan D-Bus asinkron selesai. Tidak perlu menggunakan QDBusPendingCallWatcher
dengan QCoro - cukup co_await
hasilnya saja. Saat co_awaiting, event loop Qt berjalan seperti biasa.
QDBusInterface remoteServiceInterface{serviceName, objectPath, interface};const QDBusReply<bool> isReady = co_await remoteServiceInterface.asyncCall(QStringLiteral("isReady"));
Dokumentasi lengkap di sini.
QFuture
QFuture mewakili hasil tugas asinkron. Biasanya Anda harus menggunakan QFutureWatcher
untuk mendapatkan pemberitahuan ketika masa depan sudah siap. Dengan QCoro, Anda co_await
saja!
const QFuture<int> task1 = QtConcurrent::run(....);const QFuture<int> task2 = QtConcurrent::run(....);const int a = co_await task1;const int b = co_await task2; co_return a+b;
Dokumentasi lengkap di sini.
QNetworkReply
Melakukan permintaan jaringan dengan Qt bisa jadi membosankan - pendekatan sinyal/slot merusak aliran kode Anda. Permintaan rantai dan penanganan kesalahan dengan cepat menjadi berantakan dan kode Anda dipecah menjadi beberapa fungsi. Namun tidak dengan QCoro, di mana Anda cukup co_await
QNetworkReply
selesai:
QNetworkAccessManager qnam; QNetworkReply *reply = qnam.get(QStringLiteral("https://github.com/qcoro/qcoro"));const isi otomatis = co_await balasan; balasan->deleteLater();if (balas->kesalahan() != QNetworkReply::NoError) {co_return handleError(balas); }const auto link = findLinkInReturnedHtmlCode(isi); balasan = qnam.get(link);const data otomatis = co_await balasan; balasan->deleteLater();if (balas->kesalahan() != QNetworkReply::NoError) {co_return handleError(balas); } ...
Dokumentasi lengkap di sini.
QTimer
Mungkin Anda ingin menunda eksekusi kode Anda sebentar, mungkin Anda ingin mengeksekusi beberapa kode dalam interval berulang. Ini menjadi sangat sepele dengan co_await
:
pengatur waktu QTime; timer.setInterval(1s); timer.start();for (int i = 1; i <= 100; ++i) {co_await timer;qDebug() << "Menunggu " << i << " detik..."; }qDebug() << "Selesai!";
Dokumentasi lengkap di sini.
QIODevice
QIODevice
adalah kelas dasar untuk banyak kelas di Qt yang memungkinkan data ditulis dan dibaca secara asinkron. Bagaimana cara mengetahui ada data yang siap dibaca? Anda dapat terhubung ke tunggal QIODevice::readyRead()
, atau Anda dapat menggunakan QCoro dan co_await
objek:
socket->write("PING");// Menunggu "pong"const auto data = co_await socket;co_return calculLatency(data);
Dokumentasi lengkap di sini.
Periksa dokumentasi lengkap untuk mempelajari lebih lanjut.
Terkadang co_await
tidak dapat digunakan untuk menangani hasil coroutine - biasanya saat berinteraksi dengan kode pihak ketiga yang tidak mendukung coroutine. Dalam skenario tersebut, dimungkinkan untuk menyambungkan panggilan balik lanjutan ke coroutine yang akan dipanggil secara asinkron saat coroutine selesai.
void regularFunction() {someCoroutineReturningInt().then([](int result) {// handle result}); }
Callback lanjutan juga bisa berupa coroutine dan hasil seluruh ekspresi adalah Task dengan T adalah tipe kembalian dari kelanjutannya. Berkat itu, dimungkinkan untuk co_await
seluruh rantai, atau merangkai beberapa kelanjutan .then()
.
Dokumentasi lengkap di sini.
Generator adalah coroutine yang dengan malas menghasilkan banyak nilai. Meskipun tidak ada yang khusus untuk Qt, QCoro menyediakan alat yang diperlukan bagi pengguna untuk membuat generator khusus di aplikasi Qt mereka.
QCoro menyediakan API untuk generator sinkron ( QCoro::Generator<T>
) dan generator asinkron ( QCoro::AsyncGenerator<T>
). Kedua generator menyediakan API seperti kontainer: fungsi anggota begin()
dan end()
yang mengembalikan objek seperti iterator, yang merupakan API yang terkenal dan mapan serta membuat generator kompatibel dengan algoritma yang ada.
QCoro::Generator<int> fibonacci() { kuint64 a = 0, b = 0; Q_FOREVER {co_yield b;const auto tmp = b; a = b; b+=tmp; } }void printFib(quint64 max) {untuk (auto fib : fibonacci()) {if (fib > max) {break; } std::cout << fib << std::endl; } }
Dokumentasi lengkap di sini.
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.