Konkurensi memerlukan kontrol waktu, mulai dari menunda eksekusi beberapa puluh milidetik hingga menunggu kejadian dengan batas tertentu. Ada menyediakan pernyataan delay untuk penundaan dan pernyataan select untuk menunggu salah satu dari beberapa alternatif, termasuk penerimaan entry selektif. Topik ini membahas keduanya beserta panggilan entry berbatas waktu dan panggilan entry bersyarat.
Pernyataan delay#
Pernyataan delay menerima durasi bertipe Duration dalam satuan detik, misalnya delay 0.1; untuk penundaan sepersepuluh detik, dan sah pada task maupun subprogram biasa. Tipe ini berupa bilangan titik tetap, sehingga penundaan pecahan ditulis langsung dalam detik tanpa konversi satuan. Penundaan dijamin berlangsung sekurang-kurangnya selama durasi itu, sedangkan durasi sesungguhnya bergantung pada penjadwal sistem. Penundaan berdurasi nol tetap berfungsi sebagai titik penjadwalan yang memberi kesempatan task lain bertindak.
Bentuk delay until menerima nilai waktu alih-alih durasi, sehingga cocok untuk jadwal siklik yang acuannya tetap. Program berikut mencatat tiga ketukan dengan jeda sepersepuluh detik di antaranya.
with Ada.Text_IO;
procedure Ketukan is
begin
for I in 1 .. 3 loop
Ada.Text_IO.Put_Line ("ketukan" & Integer'Image (I) & " dicatat");
delay 0.1;
end loop;
end Ketukan;# kompilasi program
gnatmake -q ketukan.adb
# jalankan program
./ketukanketukan 1 dicatat
ketukan 2 dicatat
ketukan 3 dicatatBaris keluaran tercetak dengan jarak sekitar 100 milidetik, dan urutannya pasti karena program ini tidak memiliki task lain. Untuk jadwal yang intervalnya tidak boleh bergeser, acuan delay until dihitung dari jam nyata Ada.Real_Time.Clock dan ditambah satu periode tetap pada setiap siklus, sehingga lama pekerjaan tidak terakumulasi ke interval berikutnya. Pola itu diwajibkan pada profil Ravenscar.
Penerimaan selektif dengan select#
Task yang memiliki lebih dari satu kebutuhan tunggu tidak perlu mengantre entry satu per satu. Pernyataan select pada badan task menawarkan beberapa alternatif sekaligus, misalnya accept yang dipasangkan dengan delay sebagai batas tunggu. Task menunggu sampai salah satu alternatifnya siap, lalu mengeksekusi pilihan itu saja. Alternatif accept siap apabila ada pemanggil yang sudah mengantre pada entry tersebut, sedangkan alternatif delay siap setelah waktunya tiba. Apabila dua alternatif siap pada saat yang sama, bahasa tidak menentukan pilihannya, sehingga desain tidak boleh bergantung pada urutan pilihan tersebut.
Program berikut membuat task Antena menunggu sinyal dengan batas waktu 0.3 detik, sedangkan program utama mengirimkan panggilan setelah 0.1 detik.
with Ada.Text_IO;
procedure Penerima_Tepat is
task Antena is
entry Tiba;
end Antena;
task body Antena is
begin
select
accept Tiba;
Ada.Text_IO.Put_Line ("antena: sinyal diterima");
or
delay 0.3;
Ada.Text_IO.Put_Line ("antena: batas waktu tercapai");
end select;
end Antena;
begin
delay 0.1;
Antena.Tiba;
end Penerima_Tepat;# kompilasi program
gnatmake -q penerima_tepat.adb
# jalankan program
./penerima_tepatantena: sinyal diterimaPanggilan Tiba datang lebih dulu daripada batas waktunya, sehingga alternatif accept terpilih dan penanganan sinyalnya dieksekusi. Program utama melanjutkan eksekusinya setelah rendezvous selesai. Bentuk selective accept semacam ini lazim pada task layanan yang harus tetap peka terhadap perintah sambil menunggu pekerjaan utamanya.
Pilihan ketika sinyal tak datang#
Task yang sama menunjukkan pilihan lain apabila tidak ada panggilan sebelum batas waktunya. Program berikut membiarkan task Antena menunggu tanpa panggilan sama sekali, dan program utama hanya menunggu tasknya berhenti.
with Ada.Text_IO;
procedure Penerima_Lambat is
task Antena is
entry Tiba;
end Antena;
task body Antena is
begin
select
accept Tiba;
Ada.Text_IO.Put_Line ("antena: sinyal diterima");
or
delay 0.3;
Ada.Text_IO.Put_Line ("antena: batas waktu tercapai");
end select;
end Antena;
begin
null;
end Penerima_Lambat;# kompilasi program
gnatmake -q penerima_lambat.adb
# jalankan program
./penerima_lambatantena: batas waktu tercapaiAlternatif delay terpilih karena 0.3 detik terlampaui tanpa panggilan, dan task berhenti setelah penanganannya selesai. Batas tunggu pada select berlaku untuk satu evaluasi saja. Karena itu, task layanan yang menunggu berulang memasang pernyataan select di dalam perulangan, dan setiap perulangan memiliki batas waktunya sendiri. Karena bagian penanganan batas waktunya dapat mencatat kejadian atau menyiapkan percobaan berikutnya, pola ini cocok untuk sinyal yang kehadirannya tidak pasti, misalnya detak alat yang dapat terputus. Kedua program pada topik ini hanya memiliki satu hasil seleksi per eksekusi, sehingga keluarannya tetap dapat diprediksi meskipun seleksinya melibatkan waktu.
Timed dan conditional entry call#
Batas waktu juga dapat dipasang pada sisi pemanggil melalui timed entry call. Bentuknya berupa select yang memuat satu panggilan entry yang dipasangkan dengan delay, dan timernya berlaku selama panggilan masih mengantre. Rendezvous yang sudah dimulai tidak dapat dibatalkan oleh timer karena kedua task sudah terikat pada aksi yang sama. Bentuk tanpa timer bernama conditional entry call, yang menggunakan alternatif else dan tidak menunggu sama sekali apabila panggilannya tidak langsung diterima.
Program berikut meniru antrean tiket loket. Task Pembeli_Pertama dilayani dengan rendezvous yang berlangsung 0.5 detik, sedangkan program utama mencoba membeli setelah 0.1 detik dengan batas tunggu 0.1 detik.
with Ada.Text_IO;
procedure Antrean_Loket is
task Loket is
entry Beli (Jumlah : in Integer; Total : out Integer);
end Loket;
task body Loket is
begin
accept Beli (Jumlah : in Integer; Total : out Integer) do
delay 0.5;
Total := Jumlah * 15000;
end Beli;
end Loket;
task Pembeli_Pertama;
task body Pembeli_Pertama is
Total : Integer;
begin
Loket.Beli (3, Total);
Ada.Text_IO.Put_Line ("pembeli pertama membayar" & Integer'Image (Total));
end Pembeli_Pertama;
Total : Integer;
begin
delay 0.1;
select
Loket.Beli (2, Total);
Ada.Text_IO.Put_Line ("pembeli kedua membayar" & Integer'Image (Total));
or
delay 0.1;
Ada.Text_IO.Put_Line ("antrean lambat, pemesanan kedua dibatalkan");
end select;
end Antrean_Loket;# kompilasi program
gnatmake -q antrean_loket.adb
# jalankan program
./antrean_loketantrean lambat, pemesanan kedua dibatalkan
pembeli pertama membayar 45000Panggilan program utama mengantre karena loket sedang melayani pembeli pertama. Timer 0.1 detiknya habis sebelum rendezvous dimulai, sehingga alternatif pembatalannya yang dieksekusi. Pembeli pertama selesai sesudahnya dan melaporkan total belanjanya. Urutan kedua baris itu pasti karena keduanya terjadi pada waktu yang berbeda, yaitu sekitar 0.2 detik dan 0.5 detik. Bentuk bersyaratnya hanya mengganti delay dengan else.
-- tidak-dijalankan
select
Loket.Beli (2, Total);
Ada.Text_IO.Put_Line ("pembelian berhasil");
else
Ada.Text_IO.Put_Line ("loket sedang melayani");
end select;Kesalahan umum#
Tiga kekeliruan berikut sering muncul saat delay dan select dipraktikkan.
- Menganggap
delaypresisi. Pernyataan itu menunda sekurang-kurangnya selama durasinya, sedangkan durasi sesungguhnya dapat lebih panjang pada sistem yang sibuk. Jadwal yang intervalnya tidak boleh bergeser menggunakandelay untildengan acuan tetap, bukandelayrelatif yang diulang. - Memasang timer pada panggilan yang rendezvous-nya sudah dimulai. Timer hanya membatalkan panggilan yang masih mengantre, sehingga aksi di dalam
accepttetap selesai. Rancang durasi layanan agar sesuai batas yang dijanjikan kepada pemanggil. - Menulis
selectyang seluruh alternatifnya tanpa batas waktu dan tanpaelse. Task semacam itu dapat menunggu selamanya apabila tidak ada panggilan yang datang. Pasangkan satu alternatifdelaysebagai batas tunggu.
Ringkasan#
- Pernyataan delay menunda eksekusi sekurang-kurangnya selama durasinya, sedangkan delay until menunggu sampai waktu acuannya tercapai.
- Select pada badan task menunggu salah satu alternatifnya, dan alternatif delay memberi batas tunggu pada penerimaan entry.
- Timed entry call membatalkan panggilan yang masih mengantre ketika waktunya habis, sedangkan conditional entry call tidak menunggu sama sekali.
Referensi#
- 9.6 Delay Statements, Duration, and Time — Ada Reference Manual 2022 — Menetapkan pernyataan delay beserta tipe Duration dan paket Calendar.
- 9.7.1 Selective Accept — Ada Reference Manual 2022 — Menetapkan semantik penerimaan selektif pada pernyataan select.
- 9.7.2 Timed and Conditional Entry Calls — Ada Reference Manual 2022 — Menetapkan panggilan entry berbatas waktu dan panggilan bersyarat.