Atomics
API summary (generated from the Beans source by npm run coverage): 2 types · 1 static method · 13 instance methods · 5 enum variants.
Atomic<T> হলো একটা মাত্র cell, যেটা অনেক thread কোনো lock ছাড়াই নিরাপদে পড়তে আর
বদলাতে পারে। প্রতিটা বদল একটাই ভাঙা যায় না এমন ধাপ। এই পেজে প্রতিটা operation,
পাঁচটা memory order, আর wait/notify call গুলো দেওয়া আছে। thread নিয়ে সাধারণ
আলোচনার জন্য concurrency দেখুন।
Atomic কী ধরে রাখে
“Atomic কী ধরে রাখে” সেকশনএকটা Atomic<T> ঠিক একটা integer বা একটা bool ধরে রাখে। এটা কোনো decimal বা
float ধরতে পারে না।
let counter: Atomic<i64> = new Atomic<i64>(0)একটা সরু cell তার চওড়ার মধ্যে wrap করে। Atomic<bool> হলো এক-byte-এর cell, যেটা
0 বা 1 ধরে রাখে।
Operation গুলো
“Operation গুলো” সেকশনপ্রতিটা read-modify-write operation যে value-টাকে বদলে দিল সেটাই (পুরনো value) ফেরত দেয়।
Atomic<T>.load(MemoryOrder) -> TAtomic<T>.store(T, MemoryOrder)Atomic<T>.exchange(T, MemoryOrder) -> TAtomic<T>.fetch_add(T, MemoryOrder) -> TAtomic<T>.fetch_sub(T, MemoryOrder) -> TAtomic<T>.fetch_and(T, MemoryOrder) -> TAtomic<T>.fetch_or(T, MemoryOrder) -> TAtomic<T>.fetch_xor(T, MemoryOrder) -> TAtomic<T>.compare_exchange(T, T, MemoryOrder, MemoryOrder) -> boolload(order)value-টা পড়ে;store(v, order)vলেখে।exchange(v, order)vবসায় আর পুরনো value-টা ফেরত দেয়।fetch_add(v, order)আরfetch_sub(v, order)যোগ বা বিয়োগ করে আর পুরনো value-টা ফেরত দেয়। দুইটার জন্যই একটা integer cell লাগে।fetch_and,fetch_or, আরfetch_xorএকটা bitwise operation করে আর পুরনো value-টা ফেরত দেয়।compare_exchange(expected, desired, success_order, failure_order)cell-টাকেexpected-এর সাথে মেলায়; মিলে গেলেdesiredবসায় আরtrueদেয়, না মিললে cell-টাকে যেমন আছে তেমন রেখে দিয়েfalseদেয়। এটা দুইটা order নেয়: একটা সেই পথের জন্য যেটা লিখল, আরেকটা সেই পথের জন্য যেটা অন্য value পেয়ে কিছুই করল না।
bitwise আর exchange operation গুলো Atomic<bool>-এও কাজ করে; fetch_add আর
fetch_sub করে না।
MemoryOrder
“MemoryOrder” সেকশনপ্রতিটা operation একটা memory order নেয়, যেটা বলে দেয় তার ordering কতটা কড়া হতে
হবে। MemoryOrder-এ ঠিক পাঁচটা selector আছে:
MemoryOrder.relaxedMemoryOrder.acquireMemoryOrder.releaseMemoryOrder.acq_relMemoryOrder.seq_cst
Ordering-এর নিয়ম
“Ordering-এর নিয়ম” সেকশনযেসব order-এর কোনো অর্থ নেই, compiler সেগুলো বাতিল করে দেয়:
- একটা
loadreleaseবাacq_relব্যবহার করতে পারে না। - একটা
storeacquireবাacq_relব্যবহার করতে পারে না। - একটা
compare_exchange-এর failure orderreleaseব্যবহার করতে পারে না, আর তার success order-এর চেয়ে কড়া হতে পারে না।
এগুলোর যেকোনোটা ভাঙলে compile error হয়।
Fence
“Fence” সেকশনAtomic.fence(order) হলো একটা static call, যেটা কোনো একটা cell-এ হাত না দিয়ে
memory-কে order করে। registry-তে এর signature হলো:
Atomic<T>.fence(MemoryOrder)এটা type-এর ওপর call করা হয়, আর call site-এ order-টা নাম ধরে বলা হয়:
Atomic.fence(MemoryOrder.seq_cst)Wait আর notify
“Wait আর notify” সেকশনএগুলো একটা thread-কে ঘুমাতে দেয়, একটা cell বদলানো পর্যন্ত।
Atomic<T>.wait(T, MemoryOrder)Atomic<T>.wait_timeout(T, int, MemoryOrder) -> boolAtomic<T>.notify_one() -> intAtomic<T>.notify_all() -> intwait(expected, order)block করে থাকে যতক্ষণ cell-টা এখনোexpectedধরে রাখে।wait_timeout(expected, nanos, order)nanosন্যানোসেকেন্ড পর্যন্ত অপেক্ষা করে, আর সময় ফুরিয়ে গেলেtrueদেয়।notify_one()একজন waiter-কে জাগায় আরnotify_all()সবাইকে জাগায়; প্রতিটা কতজন জাগল সেটা ফেরত দেয়।
একটা wakeup শুধুই একটা ইঙ্গিত। জাগার পর সব সময় একটা loop-এ value-টা আবার যাচাই করতে হয়।
পুরো উদাহরণ
“পুরো উদাহরণ” সেকশনদুইটা thread থেকে চালানো একটা relaxed counter, তারপর সেটা পড়ে নেওয়া:
import std.ioimport std.thread
fn main() { let counter: Atomic<i64> = new Atomic<i64>(0)
let first: Thread<int> = thread.spawn(fn() -> int { var i: int = 0 for i < 10000 { counter.fetch_add(1, MemoryOrder.relaxed) i += 1 } return 0 }) let second: Thread<int> = thread.spawn(fn() -> int { var i: int = 0 for i < 10000 { counter.fetch_add(1, MemoryOrder.relaxed) i += 1 } return 0 }) first.join() second.join()
let took: bool = counter.compare_exchange(20000, 0, MemoryOrder.acq_rel, MemoryOrder.acquire) Atomic.fence(MemoryOrder.seq_cst) io.println("counted {counter.load(MemoryOrder.acquire)} reset {took}")}আরও দেখুন
“আরও দেখুন” সেকশন- Ownership handle,
AtomicIntএকটা সহজ, সব সময় sequentially consistent counter। - Concurrency, thread, channel, আর lock।