std.poll
API সারমর্ম (Beans source থেকে npm run coverage দিয়ে বানানো): 1টা package function · 3টা type · 1টা constructor · 4টা static method · 7টা instance method · 7টা public field।
std.poll দিয়ে একটা thread একসাথে অনেক descriptor-এর জন্য অপেক্ষা করতে পারে, আর জানতে পারে কোনগুলো ready হলো। Linux-এ এটা epoll ব্যবহার করে, macOS-এ kqueue, দুটোই level-triggered মোডে। source দেখুন এখানে:
stdlib/std/poll/poll.b।
import std.pollপ্রতিটা descriptor-কে poller-এ register করা হয় একটা token-এর নিচে, token-টা নিজে বেছে নেওয়া হয়। wait করার সময় প্রতিটা ready descriptor তার token নিয়ে ফিরে আসে। token নিজের বেছে নেওয়া value, কখনোই raw descriptor না, তাই ওটাকে নিজের data-র index বা id হিসেবে ব্যবহার করা যায়। এটা জরুরি, কারণ একটা descriptor number বন্ধ হওয়ার সঙ্গে সঙ্গেই আবার নতুন করে ব্যবহার হয়ে যায় — তাই ওটার উপর keyed কোনো event handle করার সময়ে হয়তো অন্য কোনো জিনিসকে নির্দেশ করছে।
Interest
“Interest” সেকশনএকটা descriptor-এ কী জন্য নজর রাখতে চাওয়া হচ্ছে সেটা। সাধারণ একটা value, তাই একটা তৈরি করে বারবার ব্যবহার করা যায়।
pub class Interestnew Interest(read: bool, write: bool)
pub read: boolpub write: bool
pub static fn read_only() -> Interestpub static fn write_only() -> Interestpub static fn both() -> Interestread_onlyincoming data-র জন্য নজর রাখে, কিংবা একটা listener-এ connection আসার জন্য।write_onlyলেখার জায়গার জন্য নজর রাখে।bothদুটোর জন্যই।
Event
“Event” সেকশনএকটা descriptor যেটা ready হলো, যেভাবে wait ফেরত দেয়।
pub class Eventpub token: intpub readable: boolpub writable: boolpub hangup: boolpub error: booltokenহলোadd-এ যে value দেওয়া হয়েছিল, যা caller-এর নিজের হিসেবেই বোঝার।readableবলতে বোঝায় data এসেছে বা একটা listener-এ connection অপেক্ষা করছে।writableবলতে বোঝায় লেখার জায়গা আছে।hangupবলতে বোঝায় peer চলে গেছে; একটা socket একইসাথে readable আর hung up হতে পারে, আর তখন buffer-এ জমে থাকা data-টা পড়া কিন্তু এখনো দরকারি।errorবলতে বোঝায় descriptor-টা নিজেই fail করেছে।
Poller
“Poller” সেকশনযে descriptor-গুলোর জন্য অপেক্ষা করা হবে তাদের সেট। এটা একটা unique class: move-only, আর drop হলে নিজেই বন্ধ হয়ে যায়।
pub unique class Poller
pub static fn open() -> Result<Poller>
pub fn add(fd: int, token: int, want: Interest) -> Result<bool>pub fn modify(fd: int, token: int, want: Interest) -> Result<bool>pub fn remove(fd: int) -> Result<bool>pub fn wait(max_events: int, timeout_ms: int) -> Result<List<Event>>pub fn wake() -> Result<bool>pub fn wake_handle() -> intpub fn close() -> Result<bool>openconstructor না হয়ে fail করতে পারে, কারণ একটা poller ভেতরে একটা pipe বহন করে যাতেwake()কাজ করে।addfd-এর উপর নজর রাখা শুরু করে, আর ready হলেtokenজানায়। একই descriptor দুবার register করলে আগেরটাকে replace করে দেয়, fail করে না।modifyএকটা descriptor কী জন্য দেখা হচ্ছে সেটা বদলায়, আর তার token-ও।removeএকটা descriptor-এর উপর নজর রাখা বন্ধ করে। descriptor বন্ধ করার আগে এটা করতে হবে। বন্ধ করলে ঠিকই kernel-এর সেট থেকে ওটা বাদ পড়ে যায়, কিন্তু এই batch-এ যে event-গুলো এর মধ্যেই আছে সেগুলো এখনো ওই token বহন করে, আর ততক্ষণে number-টা হয়তো অন্য কিছুর দখলে চলে গেছে।waitready descriptor-গুলো ফেরত দেয়, বড়জোরmax_events-টা, যেটা allocation-এর সীমা বেঁধে দেয়। negativetimeout_msঅনন্তকাল অপেক্ষা করে,0হলো non-blocking check, আর বাকি যেকোনো value বড়জোর তত মিলিসেকেন্ড অপেক্ষা করে। সময় ফুরিয়ে গেলে একটা খালি list, error না।wakeএকটা block হয়ে থাকাwait-কে চটপট ফিরিয়ে আনে। বারবার wake করলে সেগুলো একটাতেই মিশে যায়, আর একটা wake কখনো event হিসেবে জানানো হয় না।wake_handleএকটাintফেরত দেয় যেটা thread boundary পার হতে পারে। এটা descriptor না: এটা একটা slot আর একটা generation-কে নির্দেশ করে, তাই এই poller বন্ধ হওয়ার পর দেওয়া কোনো wake সেই descriptor number-এর দখল নেওয়া জিনিসে না লিখে বরংclosedkind জানায়।- poller একবার বন্ধ হলে প্রতিটা method
closedkind ফেরত দেয়।
অন্য thread থেকে wake করা
“অন্য thread থেকে wake করা” সেকশনকোনো block হয়ে থাকা poller-কে অন্য একটা thread থেকে wake করতে হলে, সেই thread poller-এর wake_handle() দিয়ে module-level function-টা ডাকে। এটা method না হয়ে একটা free function, কারণ পুরো ব্যাপারটাই এই — caller-এর হাতে Poller-টা নেই। যে poller ইতিমধ্যে বন্ধ হয়ে গেছে তার একটা বাসি handle হলে closed kind-এর একটা err।
pub fn wake(signal: int) -> Result<bool>একটা listener register করে একটা connection আসার জন্য অপেক্ষা করা:
import std.ioimport std.pollimport std.net
fn main() { let listener: net.TcpListener = net.TcpListener.bind("127.0.0.1", 0).expect("bind") let poller: poll.Poller = poll.Poller.open().expect("open") poller.add(listener.poll_handle(), 1, poll.Interest.read_only()).expect("add") let events: List<poll.Event> = poller.wait(8, 1000).expect("wait") for e in events { if e.token == 1 && e.readable { io.println("a connection is waiting") } }}আরও দেখুন
“আরও দেখুন” সেকশন- std.net, socket-গুলো একটা
poll_handle()দেয়। - std.signal, একটা
Signals-এরও একটাpoll_handle()আছে।