Bnlang ইভেন্ট লুপ
প্রতিটি Bnlang প্রোগ্রাম একটি ইভেন্ট লুপ-এ চলে, যা libuv দ্বারা সরবরাহ করা। এই লুপই async I/O চালায়: যখন একটি রিকোয়েস্ট ডিস্ক বা নেটওয়ার্কের জন্য অপেক্ষমাণ, লুপ ঘুরতে থাকে এবং প্রস্তুত অন্য কলব্যাকগুলো চালায়।
How It Works
১. আপনার স্ক্রিপ্ট উপর থেকে নিচে চলে। সিঙ্ক্রোনাস স্টেটমেন্ট সাথে সাথে এক্সিকিউট হয়।
২. Async কল (যেমন io.read_file_async, timers.set, নেটওয়ার্ক অপ) libuv-এ কাজ হস্তান্তর করে অপেক্ষা না করেই ফেরত আসে।
৩. টপ-লেভেল কোড শেষ হলে রানটাইম কন্ট্রোল ইভেন্ট লুপকে দেয়।
৪. প্রতিটি অপারেশন কমপ্লিট হলে libuv সংশ্লিষ্ট কলব্যাক কিউতে রাখে। লুপ এক একটা করে তুলে মেইন থ্রেডে চালায়।
৫. কোনো লাইভ টাইমার, খোলা স্ট্রিম, বা ইন-ফ্লাইট রিকোয়েস্ট না থাকলে প্রসেস এক্সিট করে।
Example: Timers and Async I/O
নিচের আউটপুটে লুপ দেখানো হলো কাজ করতে। লক্ষ্য করুন, সিঙ্ক্রোনাস print কল আগে চলে, তারপর লুপ শিডিউলড কলব্যাকগুলো ড্রেইন করে।
import "timers" as timers;
import "io" as io;
print("a");
timers.set(0, function () {
print("timer fired");
});
io.read_file_async("greeting.txt", function (err, data) {
if (err != null) { print("read err:", err); return; }
print("file:", data);
});
print("b");
// Output (file order depends on disk timing):
// a
// b
// timer fired
// file: ...
What's Not Here
Bnlang এর ইভেন্ট লুপ ইচ্ছাকৃতভাবে সরল। অন্য রানটাইম থেকে আপনি যেসব আশা করতে পারেন, এর কিছু এখানে নেই:
- কোনো মাইক্রোটাস্ক কিউ নেই — কোনো Promise নেই, তাই
then/awaitমাইক্রোটাস্ক অর্ডারিং নেই। কলব্যাক তাদের I/O যে ক্রমে কমপ্লিট হয় সেই ক্রমে চলে। process.nextTickবাsetImmediateনেই — পরের লুপ-টার্ন পর্যন্ত ডিফার করতেtimers.set(0, fn)ব্যবহার করুন।- স্ক্রিপ্টের কাছে দৃশ্যমান কোনো ব্যাকগ্রাউন্ড থ্রেড নেই — ভারী I/O ভিতরে libuv এর থ্রেড পুল ব্যবহার করে, কিন্তু আপনার স্ক্রিপ্ট সবসময় মেইন থ্রেডে চলে।
Best Practices
- কলব্যাক ছোট রাখুন। এরা প্রতিটা অন্য ইন-ফ্লাইট রিকোয়েস্টের সাথে লুপ শেয়ার করে।
- CPU-ভারী কাজকে
timers.set(0, ...)দিয়ে আলাদা চাঙ্কে ভাগ করুন, যাতে অন্য কলব্যাক টার্ন পায়। - যেসব স্ট্রিম ও ইন্টারভ্যাল টাইমার আপনার আর প্রয়োজন নেই, ক্লোজ/ক্লিয়ার করুন — না করলে লুপ (এবং আপনার প্রসেস) জীবিত থাকবে।