Contoh Coroutine C++

Contoh Coroutine C



Coroutine menyediakan fitur bahasa yang memungkinkan Anda menulis kode asinkron dengan cara yang lebih terorganisir dan linier, sehingga mendorong pendekatan terstruktur dan berurutan. Mereka memberikan mekanisme untuk menjeda dan memulai ulang eksekusi fungsi pada kejadian tertentu tanpa menghentikan keseluruhan thread. Coroutine berguna saat menangani tugas yang memerlukan menunggu operasi I/O seperti membaca file atau mengirim panggilan jaringan.

Coroutine didasarkan pada konsep generator di mana suatu fungsi dapat menghasilkan nilai dan kemudian dilanjutkan untuk melanjutkan eksekusi. Coroutine menyediakan alat yang ampuh untuk mengelola operasi asinkron dan dapat meningkatkan kualitas kode Anda secara keseluruhan.

Kegunaan Coroutine

Coroutine diperlukan karena beberapa alasan dalam pemrograman modern, khususnya dalam bahasa seperti C++. Berikut adalah beberapa alasan utama mengapa coroutine bermanfaat:







Coroutine memberikan solusi elegan untuk pemrograman asinkron. Mereka memungkinkan untuk membuat kode yang tampak berurutan dan memblokir yang lebih mudah untuk dipikirkan dan dipahami. Coroutine dapat menangguhkan eksekusinya pada titik tertentu tanpa memblokir thread, sehingga memungkinkan operasi paralel dari tugas lain. Oleh karena itu, sumber daya sistem dapat digunakan secara lebih efektif, dan daya tanggap meningkat dalam aplikasi yang melibatkan operasi I/O atau menunggu kejadian eksternal.



Mereka mungkin membuat kode lebih mudah untuk dipahami dan dipelihara. Dengan menghilangkan rantai panggilan balik yang rumit atau mesin status, coroutine memungkinkan kode ditulis dalam gaya yang lebih linier dan berurutan. Hal ini meningkatkan pengorganisasian kode, mengurangi penumpukan, dan membuat logika mudah dipahami.



Coroutine menyediakan cara terstruktur untuk menangani konkurensi dan paralelisme. Mereka memungkinkan Anda untuk mengekspresikan pola koordinasi yang kompleks dan alur kerja asinkron menggunakan sintaksis yang lebih intuitif. Tidak seperti model threading tradisional yang threadnya mungkin diblokir, coroutine dapat mengosongkan sumber daya sistem dan memungkinkan multitasking yang efisien.





Mari buat beberapa contoh untuk mendemonstrasikan implementasi coroutine di C++.

Contoh 1: Coroutine Dasar

Contoh coroutine dasar diberikan sebagai berikut:



#termasuk

#sertakan

struktur Corout ini {

struktur janji_tipe {

IniCorout get_return_object ( ) { kembali { } ; }

std :: menangguhkan_tidak pernah inisial_menangguhkan ( ) { kembali { } ; }

std :: menangguhkan_tidak pernah final_suspend ( ) tidak, kecuali { kembali { } ; }

ruang kosong pengecualian_tidak tertangani ( ) { }

ruang kosong kembali_batal ( ) { }

} ;

bool menunggu_siap ( ) { kembali PALSU ; }

ruang kosong menunggu_menangguhkan ( std :: coroutine_handle <> H ) { }

ruang kosong tunggu_resume ( ) { std :: cout << 'Coroutine dilanjutkan.' << std :: akhir ; }

} ;

Ini Corout foo ( ) {

std :: cout << 'Coroutine telah dimulai.' << std :: akhir ;

bersama_menunggu std :: menangguhkan_selalu { } ;

bersama_kembali ;

}

ke dalam utama ( ) {

mobil kr = foo ( ) ;

std :: cout << 'Coroutine telah dibuat.' << std :: akhir ;

kr. tunggu_resume ( ) ;

std :: cout << 'Coroutine selesai.' << std :: akhir ;

kembali 0 ;

}

Mari kita lihat kode yang diberikan sebelumnya dan jelaskan secara detail:

Setelah menyertakan file header yang diperlukan, kami mendefinisikan struct “ThisCorout” yang mewakili coroutine. Di dalam “ThisCorout”, struct lain yaitu “promise_type” didefinisikan yang menangani janji coroutine. Struktur ini menyediakan berbagai fungsi yang dibutuhkan oleh mesin coroutine.

Di dalam tanda kurung, kita menggunakan fungsi get_return_object(). Ini mengembalikan objek coroutine itu sendiri. Dalam contoh ini, ia mengembalikan objek “ThisCorout” yang kosong. Kemudian, fungsi initial_suspend() dipanggil yang menentukan perilaku saat coroutine pertama kali dimulai. std::suspend_never berarti coroutine tidak boleh ditangguhkan pada awalnya.

Setelah itu, kita memiliki fungsi final_suspend() yang menentukan perilaku ketika coroutine akan selesai. std::suspend_never berarti coroutine tidak boleh ditangguhkan sebelum finalisasinya.

Jika coroutine memunculkan pengecualian, metode unhandled_Exception() akan dipanggil. Dalam contoh ini, ini adalah fungsi kosong, namun Anda dapat menangani pengecualian sesuai kebutuhan. Ketika coroutine berakhir tanpa menghasilkan nilai, metode return_void() dipanggil. Dalam hal ini, ini juga merupakan fungsi kosong.

Kami juga mendefinisikan tiga fungsi anggota dalam “ThisCorout”. Fungsi menunggu_ready() dipanggil untuk memeriksa apakah coroutine siap melanjutkan eksekusi. Dalam contoh ini, selalu menghasilkan false yang menunjukkan bahwa coroutine belum siap untuk segera dilanjutkan. Saat coroutine akan ditangguhkan, metode menunggu_suspend() dipanggil. Di sini, ini adalah fungsi kosong yang berarti tidak diperlukan penangguhan. Program ini memanggil wait_resume() ketika coroutine dilanjutkan setelah penangguhan. Itu hanya menampilkan pesan yang menyatakan bahwa coroutine telah dilanjutkan.

Baris kode berikutnya mendefinisikan fungsi coroutine foo(). Di dalam foo(), kita mulai dengan mencetak pesan yang menyatakan bahwa coroutine telah dimulai. Kemudian, co_await std::suspend_always{} digunakan untuk menangguhkan coroutine dan menunjukkan bahwa coroutine dapat dilanjutkan di lain waktu. Pernyataan co_return digunakan untuk menyelesaikan coroutine tanpa mengembalikan nilai apa pun.

Dalam fungsi main(), kita membuat objek “cr” bertipe “ThisCorout” dengan memanggil foo(). Ini membuat dan memulai coroutine. Kemudian, pesan yang menyatakan bahwa coroutine telah dibuat akan dicetak. Selanjutnya, kita memanggil wait_resume() pada objek coroutine “cr” untuk melanjutkan eksekusinya. Di dalam menunggu_resume(), pesan “The Coroutine dilanjutkan” dicetak. Terakhir, kami menampilkan pesan yang menyatakan bahwa coroutine telah selesai sebelum program dihentikan.

Saat Anda menjalankan program ini, outputnya adalah sebagai berikut:

Contoh 2: Coroutine dengan Parameter dan Hasil

Sekarang, untuk ilustrasi ini, kami menyediakan kode yang mendemonstrasikan penggunaan coroutine dengan parameter dan menghasilkan dalam C++ untuk membuat perilaku seperti generator untuk menghasilkan urutan angka.

#termasuk

#sertakan

#termasuk

struktur BARUCoroutine {

struktur p_type {

std :: vektor < ke dalam > nilai-nilai ;

BARUCoroutine get_return_object ( ) { kembali { } ; }

std :: menangguhkan_selalu inisial_menangguhkan ( ) { kembali { } ; }

std :: menangguhkan_selalu final_suspend ( ) tidak, kecuali { kembali { } ; }

ruang kosong pengecualian_tidak tertangani ( ) { }

ruang kosong kembali_batal ( ) { }

std :: menangguhkan_selalu hasil_nilai ( ke dalam nilai ) {

nilai-nilai. dorong_kembali ( nilai ) ;

kembali { } ;

}

} ;

std :: vektor < ke dalam > nilai-nilai ;

struktur iterator {

std :: coroutine_handle <> paduan suara_pegangan ;

operator bodoh != ( konstanta iterator & lainnya ) konstanta { kembali paduan suara_pegangan != lainnya. paduan suara_pegangan ; }

iterator & operator ++ ( ) { paduan suara_pegangan. melanjutkan ( ) ; kembali * ini ; }

ke dalam operator * ( ) konstanta { kembali paduan suara_pegangan. janji ( ) . nilai-nilai [ 0 ] ; }

} ;

iterator dimulai ( ) { kembali iterator { std :: coroutine_handle < p_type >:: dari_janji ( janji ( ) ) } ; }

akhir iterator ( ) { kembali iterator { nullptr } ; }

std :: coroutine_handle < p_type > janji ( ) { kembali
std :: coroutine_handle < p_type >:: dari_janji ( * ini ) ; }

} ;

BARUCoroutine menghasilkanNumbers ( ) {

hasil_bersama 5 ;

hasil_bersama 6 ;

hasil_bersama 7 ;

}

ke dalam utama ( ) {

BARUCoroutine nc = menghasilkanNumbers ( ) ;

untuk ( ke dalam nilai : nc ) {

std :: cout << nilai << ' ' ;

}

std :: cout << std :: akhir ;

kembali 0 ;

}

Pada kode sebelumnya, struct NEWCoroutine mewakili generator berbasis coroutine. Ini berisi struct “p_type” bersarang yang berfungsi sebagai tipe janji untuk coroutine. Struct p_type mendefinisikan fungsi-fungsi yang diperlukan oleh mesin coroutine seperti get_return_object(), initial_suspend(), final_suspend(), unhandled_Exception(), dan return_void(). Struct p_type juga menyertakan fungsi yield_value(int value) yang digunakan untuk menghasilkan nilai dari coroutine. Itu menambahkan nilai yang diberikan ke vektor nilai.

Struct NEWCoroutine menyertakan variabel anggota std::vector yang disebut “values” yang mewakili nilai yang dihasilkan. Di dalam NEWCoroutine, terdapat iterator struct bersarang yang memungkinkan untuk mengulangi nilai yang dihasilkan. Ia memegang coro_handle yang merupakan pegangan untuk coroutine dan mendefinisikan operator seperti !=, ++, dan * untuk iterasi.

Kami menggunakan fungsi Begin() untuk membuat iterator di awal coroutine dengan mendapatkan coro_handle dari janji p_type. Sedangkan fungsi end() membuat iterator yang mewakili akhir coroutine dan dibuat dengan coro_handle nullptr. Setelah itu, fungsi janji() digunakan untuk mengembalikan tipe janji dengan membuat coroutine_handle dari janji p_type. Fungsi generateNumbers() adalah coroutine yang menghasilkan tiga nilai – 5, 6, dan 7 – menggunakan kata kunci co_yield.

Dalam fungsi main(), instance NEWCoroutine bernama “nc” dibuat dengan memanggil coroutine generateNumbers(). Ini menginisialisasi coroutine dan menangkap statusnya. Perulangan “for” berbasis rentang digunakan untuk mengulangi nilai “nc”, dan setiap nilai dicetak yang dipisahkan oleh spasi menggunakan std::cout.

Output yang dihasilkan adalah sebagai berikut:

Kesimpulan

Artikel ini menunjukkan penggunaan coroutine di C++. Kita membahas dua contoh. Untuk ilustrasi pertama, coroutine dasar dibuat dalam program C++ menggunakan fungsi coroutine. Sedangkan demonstrasi kedua dilakukan dengan memanfaatkan coroutine dengan parameter dan menghasilkan perilaku seperti generator untuk membuat rangkaian angka.