खोज…
बुनियादी चैनल संचालन: बनाना, डालना, लेना, बंद करना और बफ़र्स।
core.async
ऐसी प्रक्रियाएँ बनाने के बारे में है जो मूल्यों को लेती हैं और मूल्यों को चैनलों में core.async
हैं ।
(require [clojure.core.async :as a])
chan
साथ चैनल बनाना
आप chan
फ़ंक्शन का उपयोग करके एक चैनल बनाते हैं:
(def chan-0 (a/chan)) ;; unbuffered channel: acts as a rendez-vous point.
(def chan-1 (a/chan 3)) ;; channel with a buffer of size 3.
(def chan-2 (a/chan (a/dropping-buffer 3)) ;; channel with a *dropping* buffer of size 3
(def chan-3 (a/chan (a/sliding-buffer 3)) ;; channel with a *sliding* buffer of size 3
मूल्यों को चैनलों में डालकर >!!
और >!
आप मूल्यों के साथ एक चैनल में डाल दिया >!!
:
(a/>!! my-channel :an-item)
आप किसी भी मूल्य (स्ट्रिंग्स, संख्या, नक्शे, संग्रह, ऑब्जेक्ट, यहां तक कि अन्य चैनल, आदि) को एक चैनल में डाल सकते हैं, सिवाय nil
:
;; WON'T WORK
(a/>!! my-channel nil)
=> IllegalArgumentException Can't put nil on channel
चैनल के बफर पर निर्भर करता है, >!!
वर्तमान धागे को अवरुद्ध कर सकता है।
(let [ch (a/chan)] ;; unbuffered channel
(a/>!! ch :item)
;; the above call blocks, until another process
;; takes the item from the channel.
)
(let [ch (a/chan 3)] ;; channel with 3-size buffer
(a/>!! ch :item-1) ;; => true
(a/>!! ch :item-2) ;; => true
(a/>!! ch :item-3) ;; => true
(a/>!! ch :item-4)
;; now the buffer is full; blocks until :item-1 is taken from ch.
)
अंदर से (go ...)
ब्लॉक, आप कर सकते हैं - और चाहिए - a/>!
उपयोग करें a/>!
के बजाय a/>!!
:
(a/go (a/>! ch :item))
तार्किक व्यवहार a/>!!
के समान ही होगा a/>!!
, लेकिन केवल वास्तविक ओएस थ्रेड के बजाय गोरोइन की तार्किक प्रक्रिया अवरुद्ध हो जाएगी।
a/>!!
का उपयोग करते हुए a/>!!
अंदर (go ...)
ब्लॉक एक प्रतिमान है:
;; NEVER DO THIS
(a/go
(a/>!! ch :item))
चैनलों से मान लेना <!!
आप एक चैनल से मूल्य लेते हैं <!!
:
;; creating a channel
(def ch (a/chan 3))
;; putting some items in it
(do
(a/>!! ch :item-1)
(a/>!! ch :item-2)
(a/>!! ch :item-3))
;; taking a value
(a/<!! ch) ;; => :item-1
(a/<!! ch) ;; => :item-2
यदि चैनल में कोई आइटम उपलब्ध नहीं है, तो a/<!!
वर्तमान थ्रेड को तब तक अवरुद्ध करेगा जब तक कि चैनल में कोई मान नहीं डाला जाता है (या चैनल बंद है, बाद में देखें):
(def ch (a/chan))
(a/<!! ch) ;; blocks until another process puts something into ch or closes it
अंदर से (go ...)
ब्लॉक, आप कर सकते हैं - और चाहिए - a/<!
उपयोग करें a/<!
के बजाय a/<!!
:
(a/go (let [x (a/<! ch)] ...))
तार्किक व्यवहार a/<!!
के समान ही होगा a/<!!
, लेकिन केवल वास्तविक ओएस थ्रेड के बजाय गोरोइन की तार्किक प्रक्रिया अवरुद्ध हो जाएगी।
a/<!!
का उपयोग करते हुए a/<!!
अंदर (go ...)
ब्लॉक एक विरोधी पैटर्न है:
;; NEVER DO THIS
(a/go
(a/<!! ch))
चैनल बंद करना
आपके साथ एक चैनल को बंद a/close!
:
(a/close! ch)
एक चैनल बंद होने के बाद, और चैनल का सारा डेटा समाप्त हो गया है, हमेशा nil
वापस आएगा:
(def ch (a/chan 5))
;; putting 2 values in the channel, then closing it
(a/>!! ch :item-1)
(a/>!! ch :item-2)
(a/close! ch)
;; taking from ch will return the items that were put in it, then nil
(a/<!! ch) ;; => :item-1
(a/<!! ch) ;; => :item-2
(a/<!! ch) ;; => nil
(a/<!! ch) ;; => nil
(a/<!! ch) ;; => nil
;; once the channel is closed, >!! will have no effect on the channel:
(a/>!! ch :item-3)
=> false ;; false means the put did not succeed
(a/<!! ch) ;; => nil
अतुल्यकालिक पुट के साथ डालता है put!
a/>!!
विकल्प के रूप में a/>!!
(जो ब्लॉक हो सकता है), आप a/put!
कॉल a/put!
वैकल्पिक कॉलबैक के साथ एक चैनल में किसी अन्य थ्रेड में मान रखने के लिए।
(a/put! ch :item)
(a/put! ch :item (fn once-put [closed?] ...)) ;; callback function, will receive
क्लोजुरस्क्रिप्ट में, चूंकि वर्तमान थ्रेड को अवरुद्ध करना संभव नहीं है, a/>!!
समर्थित नहीं है, और put!
एक (go)
ब्लॉक के बाहर से एक चैनल में डेटा डालने का एकमात्र तरीका है।
एसिंक्रोनस take!
साथ लेता है take!
a/<!!
विकल्प के रूप में a/<!!
(जो वर्तमान थ्रेड को ब्लॉक कर सकता है), आप a/take!
उपयोग कर सकते a/take!
किसी चैनल से असंगत रूप से मान लेने के लिए, उसे कॉलबैक पर भेजना।
(a/take! ch (fn [x] (do something with x)))
ड्रॉपिंग और स्लाइडिंग बफ़र्स का उपयोग करना
बफ़र्स को छोड़ने और फिसलने के साथ, कभी भी ब्लॉक नहीं होता है, हालांकि, जब बफर भरा होता है, तो आप डेटा खो देते हैं। ड्रॉपिंग बफर पिछले डेटा को खो देते हैं, जबकि स्लाइडिंग बफ़र्स पहले जोड़े गए डेटा को खो देते हैं।
छोड़ने बफर उदाहरण:
(def ch (a/chan (a/dropping-buffer 2)))
;; putting more items than buffer size
(a/>!! ch :item-1)
=> true ;; put succeeded
(a/>!! ch :item-2)
=> true
(a/>!! ch :item-3)
=> false ;; put failed
;; no we take from the channel
(a/<!! ch)
=> :item-1
(a/<!! ch)
=> :item-2
(a/<!! ch)
;; blocks! :item-3 is lost
स्लाइडिंग बफर उदाहरण:
(def ch (a/chan (a/sliding-buffer 2)))
;; putting more items than buffer size
(a/>!! ch :item-1)
=> true
(a/>!! ch :item-2)
=> true
(a/>!! ch :item-3)
=> true
;; no when we take from the channel:
(a/<!! ch)
=> :item-2
(a/<!! ch)
=> :item-3
;; :item-1 was lost