प्

प्रोसेस में Elixir

5 अभ्यास

प्रोसेस के बारे में

Elixir में सारा कोड प्रोसेस के अंदर चलता है। Elixir के प्रोसेस:

  • इन्हें सिस्टम प्रोसेस से भ्रमित नहीं होना चाहिए।
  • ये हल्के होते हैं।
  • इनके कुछ खास उपयोग हैं, जैसे:
  • यह सामान्य है कि एक Elixir ऐप में सैकड़ों प्रोसेस चलें, लेकिन ऐसा ऐप भी सामान्य है जो नए प्रोसेस बिल्कुल नहीं बनाता, खासकर अगर वह कोई लाइब्रेरी है।

प्रोसेस बनाना

डिफॉल्ट रूप से एक फंक्शन उसी प्रोसेस में चलता है जिसमें उसे कॉल किया गया था। जब आपको किसी खास फंक्शन को नए प्रोसेस में साफ़-साफ़ चलाना हो, तो spawn का इस्तेमाल कीजिए:

  • spawn/1 ऐसा फंक्शन लेता है जिसे वह सीधे चलाता है।

    spawn(fn -> 2 + 2 end)
    # => #PID<0.125.0>
    
  • spawn/3 ऐसा फंक्शन लेता है जिसे वह मॉड्यूल के नाम, फंक्शन के नाम (एटम के रूप में) और उस फंक्शन को दिए जाने वाले आर्गुमेंट के ऐरे की मदद से चलाता है।

    spawn(String, :split, ["hello there", " "])
    # => #PID<0.113.0>
    
    • डेटा की इस तिकड़ी को अक्सर MFA कहा जाता है, यानी Module, Function, Arguments।
  • जैसे ही किसी प्रोसेस का फंक्शन चलना पूरा होता है, वह प्रोसेस बंद हो जाता है।

  • आप Process.alive?/1 की मदद से देख सकते हैं कि कोई प्रोसेस अब भी जीवित (यानी चल रहा) है या नहीं:

    pid = spawn(fn -> 2 + 2 end)
    Process.alive?(pid)
    # => false
    

संदेश

प्रोसेस आपस में सीधे जानकारी साझा नहीं करते। डेटा साझा करने के लिए प्रोसेस एक-दूसरे को संदेश भेजते हैं। कोड को साथ-साथ चलाने के इस तरीके को एक्टर मॉडल कहते हैं।

  • send/2 की मदद से किसी प्रोसेस को संदेश भेजिए।

    send(pid, :hello)
    
    • संदेश जिस क्रम में भेजे जाते हैं, उसी क्रम में पाने वाले प्रोसेस की मेलबॉक्स में पहुँचते हैं।
    • send यह नहीं जाँचता कि संदेश मिला या नहीं, और न ही यह कि पाने वाला प्रोसेस अब भी जीवित है या नहीं।
  • संदेश किसी भी टाइप का हो सकता है।

  • मौजूदा प्रोसेस को भेजा गया संदेश आप receive/1 की मदद से पा सकते हैं।

    • आपको संदेशों पर पैटर्न मैच करना होता है।
    • receive तब तक इंतज़ार करता है जब तक किसी भी दिए गए पैटर्न से मेल खाता कोई संदेश प्रोसेस की मेलबॉक्स में न आ जाए।
      • डिफॉल्ट रूप से यह बिना किसी समय-सीमा के इंतज़ार करता है, लेकिन after ब्लॉक की मदद से इसे एक टाइमआउट दिया जा सकता है।
    • पढ़े गए संदेश प्रोसेस की मेलबॉक्स से हट जाते हैं। बिना पढ़े संदेश वहीं अनिश्चित काल तक पड़े रहते हैं।
      • हमेशा receive/1 में एक ऐसा _ क्लॉज़ ज़रूर लिखिए जो हर संदेश को पकड़ ले, ताकि बिना पढ़े संदेश जमा होने से मेमोरी खत्म न हो जाए।
    receive do
      {:ping, sender_pid} -> send(sender_pid, :pong)
      _ -> nil
    after
      5000 ->
        {:error, "No message in 5 seconds"}
    end
    

रिसीव लूप

अगर आपको एक से ज़्यादा संदेश पाने हैं, तो आपको receive/1 को रीकर्सिव तरीके से कॉल करना होगा। एक आम तरीका यह है कि एक रीकर्सिव फंक्शन बनाया जाए, जैसे loop नाम का, जो receive/1 को कॉल करता है, संदेश के साथ कुछ करता है, और फिर और संदेशों का इंतज़ार करने के लिए खुद को कॉल करता है। अगर आपको एक receive/1 कॉल से दूसरी कॉल तक कुछ स्थिति ले जानी है, तो आप उस loop फंक्शन को एक आर्गुमेंट देकर ऐसा कर सकते हैं।

def loop(state) do
  receive do
    :increment_by_one ->
      loop(state + 1)

    {:report_state, sender_pid} ->
      send(sender_pid, state)
      loop(state)

    :stop ->
      nil

    _ ->
      loop(state)
  end
end

व्यवहार में यह तरीका सीधे शायद ही कभी इस्तेमाल किया जाता है। Elixir में कोड को साथ-साथ चलाने के लिए कुछ ऐब्स्ट्रैक्शन मिलते हैं, जैसे Agent मॉड्यूल या GenServer बिहेवियर, जो दोनों रिसीव लूप के ऊपर बने हैं। लेकिन इन ऐब्स्ट्रैक्शन का कुशलता से इस्तेमाल कर पाने के लिए इन बुनियादी बातों को समझना बहुत ज़रूरी है।

GitHub के ज़रिए संपादित करें यह लिंक नई विंडो या टैब में खुलता है।

प्रोसेस सीखिए

अभ्यास लॉक है

प्रोसेस पर अभ्यास करने के लिए 4 और अभ्यास अनलॉक कीजिए