{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## 5-10 Fiber\n", "### 5-10-1 基本的な振る舞い" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello, Fiber\n", "Hello (again)\n" ] }, { "ename": "FiberError", "evalue": "dead fiber called", "output_type": "error", "traceback": [ "\u001b[31mFiberError\u001b[0m: dead fiber called", "\u001b[37m
:10:in `resume'\u001b[0m", "\u001b[37m
:10:in `
'\u001b[0m", "\u001b[37m/Users/ariga/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/iruby-0.3/lib/iruby/backend.rb:44:in `eval'\u001b[0m", "\u001b[37m/Users/ariga/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/iruby-0.3/lib/iruby/backend.rb:44:in `eval'\u001b[0m", "\u001b[37m/Users/ariga/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/iruby-0.3/lib/iruby/backend.rb:12:in `eval'\u001b[0m", "\u001b[37m/Users/ariga/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/iruby-0.3/lib/iruby/kernel.rb:87:in `execute_request'\u001b[0m", "\u001b[37m/Users/ariga/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/iruby-0.3/lib/iruby/kernel.rb:47:in `dispatch'\u001b[0m", "\u001b[37m/Users/ariga/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/iruby-0.3/lib/iruby/kernel.rb:37:in `run'\u001b[0m", "\u001b[37m/Users/ariga/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/iruby-0.3/lib/iruby/command.rb:70:in `run_kernel'\u001b[0m", "\u001b[37m/Users/ariga/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/iruby-0.3/lib/iruby/command.rb:34:in `run'\u001b[0m", "\u001b[37m/Users/ariga/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/iruby-0.3/bin/iruby:5:in `'\u001b[0m", "\u001b[37m/Users/ariga/.rbenv/versions/2.5.1/bin/iruby:23:in `load'\u001b[0m", "\u001b[37m/Users/ariga/.rbenv/versions/2.5.1/bin/iruby:23:in `
'\u001b[0m" ] } ], "source": [ "fiber = Fiber.new {\n", " puts 'Hello, Fiber'\n", " Fiber.yield\n", " puts 'Hello (again)'\n", "}\n", "\n", "fiber.resume\n", "\n", "fiber.resume\n", "\n", "fiber.resume" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5-10-2 引数と戻り値" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "hello\n", "goodbye\n", "hello (again)\n", "goodbye (again)\n" ] } ], "source": [ "fiber = Fiber.new { |first|\n", " puts first\n", " \n", " second = Fiber.yield('goodbye')\n", " \n", " puts second\n", " \n", " 'goodbye (again)'\n", "}\n", "\n", "puts fiber.resume('hello')\n", "puts fiber.resume('hello (again)')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5-10-3 ジェネレータ" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]\n", "89\n", "144\n" ] } ], "source": [ "fib = Fiber.new {\n", " a, b = 0, 1\n", " \n", " loop do\n", " a, b = b, a+b\n", " \n", " Fiber.yield(a)\n", " end\n", "}\n", "\n", "puts 10.times.map { fib.resume }\n", "puts fib.resume\n", "puts fib.resume" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "233" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fib.resume" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- `Proc` との差異は?\n", "- @kishima: `Fiber` はmrubyのコンパイル時に並列で処理するのに使っている。並列処理はOSでやって、待ちをFiberでやっている。なお、Cygwinではこのビルドが壊れている。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5-10-4 スレッドと組み合わせた場合の制限" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "#:4 run> terminated with exception (report_on_exception is true):\n", "
:5:in `resume': fiber called across threads (FiberError)\n", "\tfrom
:5:in `block in
'\n" ] }, { "ename": "FiberError", "evalue": "fiber called across threads", "output_type": "error", "traceback": [ "\u001b[31mFiberError\u001b[0m: fiber called across threads", "\u001b[37m
:5:in `resume'\u001b[0m", "\u001b[37m
:5:in `block in
'\u001b[0m" ] } ], "source": [ "fiber = Fiber.new {\n", " puts 'OMG'\n", "}\n", "\n", "Thread.fork {\n", " fiber.resume\n", "}.join" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "#:1 run> terminated with exception (report_on_exception is true):\n", "
:2:in `yield': can't yield from root fiber (FiberError)\n", "\tfrom
:2:in `block (2 levels) in
'\n" ] }, { "ename": "FiberError", "evalue": "can't yield from root fiber", "output_type": "error", "traceback": [ "\u001b[31mFiberError\u001b[0m: can't yield from root fiber", "\u001b[37m
:2:in `yield'\u001b[0m", "\u001b[37m
:2:in `block (2 levels) in
'\u001b[0m" ] } ], "source": [ "fiber = Fiber.new {\n", " Thread.fork {\n", " Fiber.yield\n", " }.join\n", "}\n", "\n", "fiber.resume" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "次回は、「5-11 Process」から" ] } ], "metadata": { "kernelspec": { "display_name": "Ruby 2.5.1", "language": "ruby", "name": "ruby" }, "language_info": { "file_extension": ".rb", "mimetype": "application/x-ruby", "name": "ruby", "version": "2.5.1" } }, "nbformat": 4, "nbformat_minor": 2 }