LoginSignup
2
1

More than 5 years have passed since last update.

elixirでspawn, channel

Last updated at Posted at 2016-09-20

前の投稿では、Crystalをやってみる
http://qiita.com/tabetomo/items/754308a6cd48bcf56585

spawn3.cr
ch1 = Channel(String).new(1)
ch2 = Channel(String).new(1)
done = Channel(Bool).new()

spawn do
  puts ch1.receive
  puts ch2.receive
  puts ch1.receive
  done.send(true) # end
end

spawn do
  ch1.send("apple")
  ch2.send("orange")
end
ch1.send("grape")

done.receive

と言って、Crystal上でspawnで送受信する例をやってみました。このページでは同じことをgolangでやってみます。

注意、上記は、前投稿のコメント欄でいただいた修正版コードを利用させていただきました :smile: 。>karupanerura様ありがとうございます!。
(cristalではメッセージのバッファのサイズを指定できる。というので使っている)

elixirでのspawn + send/receive例

同じことをgolangでやる予定でしたが、先にelixirでやってみることにしました。elixirでは、こんな感じ。

contest.ex
defmodule Contest do
   # 関数を使っていないのでモジュールは空
end

pid1 = spawn fn -> 
        receive do 
            {sender, msg} -> IO.puts(msg)
        end
        receive do 
            {sender, msg} -> IO.puts(msg)
        end
        receive do 
            {sender, msg} -> IO.puts(msg)
            send(sender, "done")
        end
    end

send(pid1, {self, "apple"})
send(pid1, {self, "orange"})
send(pid1, {self, "grape"})

pid2 = spawn fn ->
         send(pid1, {self, "apple"})
         send(pid1, {self, "orange"})
         receive do
             msg -> IO.puts("pid2, " <> msg)
         after
             1_000 -> IO.puts("time out in pid2")
         end
     end

send(pid1, {self, "grape"})
receive do
    msg -> IO.puts("parent, " <> msg)
after
    1_000 -> IO.puts("time out in parent")
end

(解説)pid1へのsendでは、{self, "contents"}のタプルにして、自分のpid=selfを送っています。このpidは返信に使われます。pid1では、3通うけとると、sender宛に"done"を送ることにしています。pid2は、基本pid1にメッセージを送るだけですが、ここでも{self, "contents"}として返信先を書いています。3通受信後、pid1からの返信"done"が、pid2に届くのかparentに届くのか未定なので、ここではどちらでもメッセージを受け取るようにしています。pid2かparentかどちらか一方受け取れないので(受け取れない方がいつまでも待たないように)受信にタイムアウトを入れています。

実行例は、以下の通り

terminal
$ bash-3.2$ iex -S mix                                  
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4]
[hipe] [kernel-poll:false] [dtrace]                   

Compiling 1 file (.ex)                                
grape                                                 
apple                                                 
orange                                                
pid2, done                                            
time out in parent                                    
Interactive Elixir (1.3.2) - press Ctrl+C to exit (typ
)                     
iex(1)> 

elixirでは1つのspawnで1つのチャネル(のはず)ということで、cystalの例のように1つのspawnで2つのチェネル(ch1, ch2)を受信!とはいかなかったですが、なんとか近いものは動作させることができました。Elixlirでは100万個のspawnを作ってもすぐ終了する(高速!)。らしいので、ぜひ今度は是非やってみたいですね。

最後にvscodeでの画面イメージを載せておきます。
elixir.png

Ctrl`で、terminalが立ちあがって作業できるので、vscodeは便利。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1