Topik wawancara representatif

Wawancara C++26: Bagaimana sender, receiver, dan operation state bekerja bersama?

CodingSulit
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Jelaskan peran sender, receiver, dan operation state dalam std::execution C++26. Apa yang dilakukan connect dan start, dan bagaimana penyelesaian value, error, dan stopped bekerja?

Masalah dan konteks

Pertanyaan ini menguji model objek inti dalam C++26 std::execution. Mulailah dengan satu operasi asinkron minimal dan jelaskan deskripsi lazy dari sender, kontrak penyelesaian receiver, operation state yang dihasilkan oleh connect, dan titik di mana start meluncurkan komputasi.

Apa yang dievaluasi oleh pewawancara

Perbedaan kuncinya adalah antara deskripsi sender yang lazy dan operation state yang dibuat setelah koneksi: connect membangun state, sementara start memulai pekerjaan. Jelaskan bagaimana set_value, set_error, dan set_stopped bergerak melalui pipeline, apakah perubahan scheduler memengaruhi afinitas thread, dan bagaimana pembatalan mencegah efek samping baru.

Pertanyaan klarifikasi untuk ditanyakan terlebih dahulu

Pekerjaan dan backpressure

Tanyakan tentang ukuran batch, konkurensi yang diizinkan, urutan input, dan kebijakan percobaan ulang (retry) untuk penulisan yang gagal. Jawabannya menentukan apakah perlu membatasi konkurensi sender atau membatasi antrean.

Penjadwalan dan sumber penghentian (stop sources)

Tanyakan bagaimana scheduler I/O dan CPU diekspos, apakah penghentian berasal dari batas waktu (timeout) atau tindakan pengguna, dan bagaimana panggilan sistem yang sudah dikirim diselesaikan. Permintaan penghentian bukanlah penghentian paksa thread.

Sumber daya dan semantik commit

Klarifikasi kepemilikan file handle, buffer, dan file sementara, apakah penulisan bersifat idempoten, dan apakah batch parsial dapat di-rollback. Ini mendefinisikan pembersihan setelah set_error.

Kerangka jawaban 30 detik

"Saya mendeskripsikan baca, parse, dan tulis dengan adaptor sender, lalu menggunakan adaptor scheduler untuk memindahkan konteks eksekusi. Pipeline tetap lazy: connect membuat operation state dan start memulainya. Setiap tahap mengirimkan nilai sukses ke hilir, kesalahan melalui seterror, dan pembatalan melalui setstopped; satu stop token mencapai setiap tahap. Jalur penghentian memeriksa sebelum efek samping terjadi, sementara pemilik menyelesaikan dan menutup I/O yang telah dikirim serta membersihkan file sementara."

Langkah-langkah solusi terperinci

Langkah 1: Tentukan batasan nilai dan kesalahan

Tentukan tipe input dan output untuk setiap tahap dan ubah kegagalan yang dapat dipulihkan menjadi sender kesalahan eksplisit. Jangan biarkan exception melintasi batas scheduler; biarkan receiver akhir mencatat keberhasilan, kegagalan, atau penghentian.

Langkah 2: Susun pipeline yang lazy

Gunakan let_value, then, atau adaptor yang setara untuk menghubungkan pembacaan, parsing, dan penulisan. Komposisi membangun deskripsi tanpa mengalokasikan thread atau melakukan I/O; operation state memiliki state bersama apa pun yang harus bertahan lebih lama dari callback.

Langkah 3: Hubungkan dan mulai (connect and start)

Panggil connect(sender, receiver) untuk mendapatkan operation state, pertahankan dalam scope yang aktif, lalu panggil start. Receiver harus hidup lebih lama dari operation state; callback asinkron tidak dapat mereferensikan objek stack yang sudah dihancurkan.

Langkah 4: Berpindah antar konteks eksekusi

Setelah I/O selesai, gunakan scheduler sender untuk memindahkan parsing ke pool CPU, lalu kembalikan penulisan ke pool I/O yang dibatasi. Catat kapasitas antrean dan fairness; jangan menempatkan penulisan yang memblokir ke dalam pool umum yang tidak terbatas.

Langkah 5: Propagasi penghentian dan backpressure

Teruskan stop token ke setiap tahap yang dapat diinterupsi. Setelah penghentian, jangan memasukkan batch baru ke dalam antrean; batalkan atau selesaikan panggilan sistem yang sedang berjalan sesuai dengan API-nya. Ketika antrean penuh, sender pembatas (throttling) menjeda pekerjaan di hulu untuk membatasi memori.

Langkah 6: Tangani kesalahan dan efek samping parsial

Tulis ke file sementara atau catat urutan batch sebelum melakukan commit secara atomik. set_error memicu pembersihan di hilir dan penutupan handle. Percobaan ulang memerlukan batasan dan kunci idempotensi sehingga tidak dapat menduplikasi penulisan.

Langkah 7: Verifikasi konkurensi dan masa pakai (lifetime)

Uji beberapa scheduler, stop race, kegagalan parse, penulisan pendek, dan penghancuran receiver dini. Gunakan thread analyzer untuk mendeteksi race condition dan ukur waktu antrean, throughput, latensi penghentian, serta operation state yang tidak dilepaskan.

Contoh jawaban berkualitas tinggi

Sender baca memancarkan batch, sender parse berjalan pada scheduler CPU, dan sender tulis berjalan pada scheduler I/O yang dibatasi. Pipeline hanya mendeskripsikan dependensi; connect membuat operation state dan start meluncurkannya. Setiap tahap menangani penyelesaian value, error, dan stopped serta berbagi stop token. Penghentian memblokir batch baru, memungkinkan I/O yang telah dikirim ditutup dengan aman, dan menggunakan file sementara ditambah ID batch untuk percobaan ulang yang idempoten. Pengujian mencakup perpindahan scheduler, backpressure, stop race, dan masa pakai receiver.

Kesalahan umum

  • Kesalahan: Mengasumsikan sender yang telah dibuat sudah berjalan. → Mengapa: Sender bersifat lazy. → Perbaikan: Nyatakan batas connect/start.
  • Kesalahan: Menangani exception tetapi tidak menangani penyelesaian stopped. → Mengapa: Stop adalah saluran penyelesaian yang terpisah. → Perbaikan: Terapkan seterror dan setstopped.
  • Kesalahan: Mematikan thread saat pembatalan. → Mengapa: Thread mungkin memiliki file handle atau penulisan parsial. → Perbaikan: Propagasikan stop token dan lakukan unwinding dengan aman.
  • Kesalahan: Memasukkan batch ke dalam antrean tanpa batas. → Mengapa: Kurangnya backpressure dapat menghabiskan memori. → Perbaikan: Batasi konkurensi, kapasitas antrean, dan percobaan ulang.

Pertanyaan dan jawaban lanjutan

Pertanyaan lanjutan 1: Mengapa tidak menggunakan future secara langsung?

Sender/receiver membuat penjadwalan, pembatalan, dan tiga saluran penyelesaian dapat dikomposisikan serta memberikan kontrol masa pakai pada waktu koneksi. Future biasanya memerlukan konvensi tambahan untuk propagasi penghentian dan kesalahan.

Pertanyaan lanjutan 2: Bisakah sender dihancurkan setelah start?

Deskripsi sender sementara dapat dihancurkan, tetapi operation state, receiver, dan sumber daya yang ditangkap harus tetap valid hingga selesai. Objek tugas atau scope harus memilikinya.

Pertanyaan lanjutan 3: Apakah set_stopped me-rollback setiap efek samping?

Tidak. Ini melaporkan penyelesaian yang dihentikan; I/O yang sudah dikirim mungkin tidak di-rollback. File sementara, commit yang idempoten, atau kompensasi diperlukan untuk konsistensi.

Pertanyaan lanjutan 4: Bagaimana Anda membuktikan penulisan tidak diduplikasi?

Tetapkan ID batch yang stabil, periksa ID yang telah di-commit sebelum menulis, dan biarkan percobaan ulang hanya menulis ID yang hilang. Injeksikan kegagalan, restart, dan stop race, lalu bandingkan log commit dengan file akhir.

Sumber publik

Pertanyaan terkait

Alat wawancara terkait

Gunakan Tangkapan Layar untuk perintah coding

Ambil tangkapan layar soal, lalu telusuri batasan, solusi, kode, edge case, dan kompleksitas secara berurutan.

Lihat alat