polyphony 0.41 → 0.42

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/Gemfile.lock +5 -5
  4. data/Rakefile +1 -1
  5. data/TODO.md +19 -9
  6. data/docs/_config.yml +56 -7
  7. data/docs/_sass/custom/custom.scss +0 -30
  8. data/docs/_sass/overrides.scss +0 -46
  9. data/docs/{user-guide → _user-guide}/all-about-timers.md +0 -0
  10. data/docs/_user-guide/index.md +9 -0
  11. data/docs/{user-guide → _user-guide}/web-server.md +0 -0
  12. data/docs/api-reference/index.md +9 -0
  13. data/docs/api-reference/polyphony-process.md +1 -1
  14. data/docs/api-reference/thread.md +1 -1
  15. data/docs/faq.md +21 -11
  16. data/docs/getting-started/index.md +10 -0
  17. data/docs/getting-started/installing.md +2 -6
  18. data/docs/getting-started/overview.md +507 -0
  19. data/docs/getting-started/tutorial.md +27 -19
  20. data/docs/index.md +1 -1
  21. data/docs/main-concepts/concurrency.md +0 -5
  22. data/docs/main-concepts/design-principles.md +2 -12
  23. data/docs/main-concepts/index.md +9 -0
  24. data/examples/core/01-spinning-up-fibers.rb +1 -0
  25. data/examples/core/03-interrupting.rb +4 -1
  26. data/examples/core/04-handling-signals.rb +19 -0
  27. data/examples/performance/thread-vs-fiber/polyphony_server.rb +6 -18
  28. data/examples/performance/thread-vs-fiber/polyphony_server_read_loop.rb +58 -0
  29. data/examples/performance/xx-array.rb +11 -0
  30. data/examples/performance/xx-fiber-switch.rb +9 -0
  31. data/examples/performance/xx-snooze.rb +15 -0
  32. data/ext/polyphony/fiber.c +0 -3
  33. data/ext/polyphony/libev_agent.c +234 -19
  34. data/ext/polyphony/libev_queue.c +3 -1
  35. data/ext/polyphony/polyphony.c +0 -10
  36. data/ext/polyphony/polyphony.h +6 -6
  37. data/ext/polyphony/thread.c +8 -36
  38. data/lib/polyphony.rb +5 -2
  39. data/lib/polyphony/core/channel.rb +2 -2
  40. data/lib/polyphony/core/global_api.rb +2 -2
  41. data/lib/polyphony/core/resource_pool.rb +2 -2
  42. data/lib/polyphony/extensions/core.rb +2 -3
  43. data/lib/polyphony/version.rb +1 -1
  44. data/polyphony.gemspec +1 -1
  45. data/test/test_agent.rb +49 -2
  46. metadata +16 -20
  47. data/docs/_includes/head.html +0 -40
  48. data/docs/_includes/nav.html +0 -51
  49. data/docs/_includes/prevnext.html +0 -17
  50. data/docs/_layouts/default.html +0 -106
  51. data/docs/api-reference.md +0 -11
  52. data/docs/api-reference/gyro-async.md +0 -57
  53. data/docs/api-reference/gyro-child.md +0 -29
  54. data/docs/api-reference/gyro-queue.md +0 -44
  55. data/docs/api-reference/gyro-timer.md +0 -51
  56. data/docs/api-reference/gyro.md +0 -25
  57. data/docs/getting-started.md +0 -10
  58. data/docs/main-concepts.md +0 -10
  59. data/docs/user-guide.md +0 -10
  60. data/examples/core/forever_sleep.rb +0 -19
@@ -1,40 +0,0 @@
1
- <head>
2
- <meta charset="UTF-8">
3
- <meta http-equiv="X-UA-Compatible" content="IE=Edge">
4
-
5
- {% if site.plugins.jekyll-seo == nil %}
6
- <title>{{ page.title }} - {{ site.title }}</title>
7
-
8
- {% if page.description %}
9
- <meta name="Description" content="{{ page.description }}">
10
- {% endif %}
11
- {% endif %}
12
-
13
- <link rel="shortcut icon" href="{{ '/favicon.ico' | relative_url }}" type="image/x-icon">
14
-
15
- <link rel="stylesheet" href="{{ '/assets/css/just-the-docs.css' | relative_url }}">
16
-
17
- {% if site.ga_tracking != nil %}
18
- <script async src="https://www.googletagmanager.com/gtag/js?id={{ site.ga_tracking }}"></script>
19
- <script>
20
- window.dataLayer = window.dataLayer || [];
21
- function gtag(){dataLayer.push(arguments);}
22
- gtag('js', new Date());
23
-
24
- gtag('config', "{{ site.ga_tracking }}");
25
- </script>
26
-
27
- {% endif %}
28
-
29
- {% if site.search_enabled != false %}
30
- <script type="text/javascript" src="{{ '/assets/js/vendor/lunr.min.js' | relative_url }}"></script>
31
- {% endif %}
32
- <script type="text/javascript" src="{{ '/assets/js/just-the-docs.js' | relative_url }}"></script>
33
-
34
- <meta name="viewport" content="width=device-width, initial-scale=1">
35
-
36
- {% seo %}
37
-
38
- {% include head_custom.html %}
39
-
40
- </head>
@@ -1,51 +0,0 @@
1
- <nav role="navigation" aria-label="Main navigation">
2
- <ul class="navigation-list">
3
- {%- assign pages_list = site.html_pages | sort:"nav_order" -%}
4
- {%- for node in pages_list -%}
5
- {%- unless node.nav_exclude -%}
6
- {%- if node.parent == nil -%}
7
- <li class="navigation-list-item
8
- {% if page.url == node.url %} active{% endif %}
9
- {% if node.section %}section-title{% endif %}
10
- ">
11
- {%- if page.parent == node.title or page.grand_parent == node.title -%}
12
- {%- assign first_level_url = node.section_link | node.url | relative_url -%}
13
- {%- endif -%}
14
- {%- if node.section -%}
15
- <span class="section-title">{{ node.title }}</span>
16
- {%- else -%}
17
- <a href="{{ node.url | relative_url }}" class="navigation-list-link{% if page.url == node.url %} active{% endif %}">{{ node.title }}</a>
18
- {%- endif -%}
19
- {%- if node.has_children -%}
20
- {%- if node.alphabetical_order -%}
21
- {%- assign children_list = site.html_pages | where: "parent", node.title | sort:"title" -%}
22
- {%- else -%}
23
- {%- assign children_list = site.html_pages | where: "parent", node.title | sort:"nav_order" -%}
24
- {%- endif -%}
25
- <ul class="navigation-list-child-list ">
26
- {%- for child in children_list -%}
27
- <li class="navigation-list-item {% if page.url == child.url or page.parent == child.title %} active{% endif %}">
28
- {%- if page.url == child.url or page.parent == child.title -%}
29
- {%- assign second_level_url = child.url | relative_url -%}
30
- {%- endif -%}
31
- <a href="{{ child.url | relative_url }}" class="navigation-list-link{% if page.url == child.url %} active{% endif %}">{{ child.title }}</a>
32
- {%- if child.has_children -%}
33
- {%- assign grand_children_list = site.html_pages | where: "parent", child.title | sort:"nav_order" -%}
34
- <ul class="navigation-list-child-list">
35
- {%- for grand_child in grand_children_list -%}
36
- <li class="navigation-list-item {% if page.url == grand_child.url %} active{% endif %}">
37
- <a href="{{ grand_child.url | relative_url }}" class="navigation-list-link{% if page.url == grand_child.url %} active{% endif %}">{{ grand_child.title }}</a>
38
- </li>
39
- {%- endfor -%}
40
- </ul>
41
- {%- endif -%}
42
- </li>
43
- {%- endfor -%}
44
- </ul>
45
- {%- endif -%}
46
- </li>
47
- {%- endif -%}
48
- {%- endunless -%}
49
- {%- endfor -%}
50
- </ul>
51
- </nav>
@@ -1,17 +0,0 @@
1
- {%- for node in site.html_pages -%}
2
- {%- if page.prev_title == node.title -%}
3
- {%- assign prev_url = node.url -%}
4
- {%- endif -%}
5
- {%- if page.next_title == node.title -%}
6
- {%- assign next_url = node.url -%}
7
- {%- endif -%}
8
- {%- endfor -%}
9
- <div id="prevnext">
10
- {%- if prev_url -%}
11
- <span class="prev"><a href="{{prev_url | relative_url}}">☜ {{page.prev_title}}</a></span>
12
- {%- endif -%}
13
- {%- if next_url -%}
14
- <span class="next"><a href="{{next_url | relative_url}}">{{page.next_title}} ☞</a></span>
15
- {%- endif -%}
16
- <span class="clear">&nbsp;</span>
17
- </div>
@@ -1,106 +0,0 @@
1
- ---
2
- layout: table_wrappers
3
- ---
4
-
5
- <!DOCTYPE html>
6
-
7
- <html lang="{{ site.lang | default: "en-US" }}">
8
- {% include head.html %}
9
- <body>
10
- <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
11
- <symbol id="link" viewBox="0 0 16 16">
12
- <title>Link</title>
13
- <path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path>
14
- </symbol>
15
- </svg>
16
-
17
- <div class="page-wrap">
18
- <div class="side-bar">
19
- <div class="site-header">
20
- <a href="{{ site.url }}{{ site.baseurl }}" class="site-title lh-tight">{% include title.html %}</a>
21
- <button class="menu-button fs-3 js-main-nav-trigger" data-text-toggle="Hide" type="button">Menu</button>
22
- </div>
23
-
24
- <div class="navigation main-nav js-main-nav">
25
- {% include nav.html %}
26
- </div>
27
- <footer class="site-footer">
28
- <p class="text-small text-grey-dk-000 mb-4">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
29
- </footer>
30
- </div>
31
- <div class="main-content-wrap js-main-content" tabindex="0">
32
- <div class="main-content">
33
- <div class="page-header js-page-header">
34
- {% if site.search_enabled != false %}
35
- <div class="search">
36
- <div class="search-input-wrap">
37
- <input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search {{ site.title }}" aria-label="Search {{ site.title }}" autocomplete="off">
38
- <svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
39
- </div>
40
- <div class="js-search-results search-results-wrap"></div>
41
- </div>
42
- {% endif %}
43
- {% if site.aux_links != nil %}
44
- <ul class="list-style-none text-small aux-nav">
45
- {% for link in site.aux_links %}
46
- <li class="d-inline-block my-0{% unless forloop.last %} mr-2{% endunless %}"><a href="{{ link.last }}">{{ link.first }}</a></li>
47
- {% endfor %}
48
- </ul>
49
- {% endif %}
50
- </div>
51
- <div class="page">
52
- {% unless page.url == "/" %}
53
- {% if page.parent %}
54
- <nav class="breadcrumb-nav">
55
- <ol class="breadcrumb-nav-list">
56
- {% if page.grand_parent %}
57
- <li class="breadcrumb-nav-list-item"><a href="{{ first_level_url }}">{{ page.grand_parent }}</a></li>
58
- <li class="breadcrumb-nav-list-item"><a href="{{ second_level_url }}">{{ page.parent }}</a></li>
59
- {% else %}
60
- <li class="breadcrumb-nav-list-item"><a href="{{ first_level_url }}">{{ page.parent }}</a></li>
61
- {% endif %}
62
- <li class="breadcrumb-nav-list-item"><span>{{ page.title }}</span></li>
63
- </ol>
64
- </nav>
65
- {% endif %}
66
- {% endunless %}
67
- <div id="main-content" class="page-content" role="main">
68
- {% if site.heading_anchors != false %}
69
- {% include vendor/anchor_headings.html html=content beforeHeading="true" anchorBody="<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><use xlink:href=\"#link\"></use></svg>" anchorClass="anchor-heading" %}
70
- {% else %}
71
- {{ content }}
72
- {% endif %}
73
-
74
- {% if page.prev_title or page.next_title %}
75
- {% include prevnext.html %}
76
- {% endif %}
77
-
78
- {% if page.has_children == true and page.has_toc != false %}
79
- <hr>
80
- <h2 class="text-delta">Table of contents</h2>
81
- {% assign children_list = site.pages | sort:"nav_order" %}
82
- <ul>
83
- {% for child in children_list %}
84
- {% if child.parent == page.title and child.title != page.title %}
85
- <li>
86
- <a href="{{ child.url | absolute_url }}">{{ child.title }}</a>{% if child.summary %} - {{ child.summary }}{% endif %}
87
- </li>
88
- {% endif %}
89
- {% endfor %}
90
- </ul>
91
- {% endif %}
92
-
93
- {% if site.footer_content != nil %}
94
- <hr>
95
- <footer role="contentinfo">
96
- <p class="text-small text-grey-dk-000 mb-0">{{ site.footer_content }}</p>
97
- </footer>
98
- {% endif %}
99
-
100
- </div>
101
- </div>
102
- </div>
103
- </div>
104
-
105
- </body>
106
- </html>
@@ -1,11 +0,0 @@
1
- ---
2
- layout: page
3
- title: API Reference
4
- description: Lorem ipsum
5
- has_children: true
6
- alphabetical_order: true
7
- section: true
8
- has_toc: false
9
- nav_order: 5
10
- section_link: /api-reference/exception
11
- ---
@@ -1,57 +0,0 @@
1
- ---
2
- layout: page
3
- title: Gyro::Async
4
- parent: API Reference
5
- permalink: /api-reference/gyro-async/
6
- ---
7
- # Gyro::Async
8
-
9
- `Gyro::Async` encapsulates a libev [async
10
- watcher](http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_ev_async_code_how_to_wake_up_an),
11
- allowing thread-safe synchronisation and signalling. `Gyro::Async` watchers are
12
- used both directly and indirectly in Polyphony to implement
13
- [queues](../gyro-queue/), await fibers and threads, and auxiliary features such
14
- as [thread pools](../polyphony-threadpool/).
15
-
16
- A `Gyro::Async` watcher instance is shared across two or more fibers (across one
17
- or more threads), where one fiber waits to be signalled by calling
18
- `Gyro::Async#await`, and one or more other fibers do the signalling by calling
19
- `Gyro::Async#signal`:
20
-
21
- ```ruby
22
- async = Gyro::Async.new
23
- spin do
24
- sleep 1
25
- async.signal
26
- end
27
-
28
- async.await
29
- ```
30
-
31
- The signalling of async watchers is compressed, which means that multiple
32
- invocations of `Gyro::Async#signal` before the event loop can continue will
33
- result the watcher being signalled just a single time.
34
-
35
- In addition to signalling, the async watcher can also be used to transfer an
36
- arbitrary value to the awaitng fiber. See `#signal` for an example.
37
-
38
- ## Instance methods
39
-
40
- ### #await → object
41
-
42
- Blocks the current thread until the watcher is signalled.
43
-
44
- ### #initialize
45
-
46
- Initializes the watcher instance.
47
-
48
- ### #signal(value = nil) → async
49
-
50
- Signals the watcher, causing the fiber awaiting the watcher to become runnable
51
- and be eventually resumed with the given value.
52
-
53
- ```ruby
54
- async = Gyro::Async.new
55
- spin { async.signal('foo') }
56
- async.await #=> 'foo'
57
- ```
@@ -1,29 +0,0 @@
1
- ---
2
- layout: page
3
- title: Gyro::Child
4
- parent: API Reference
5
- permalink: /api-reference/gyro-child/
6
- ---
7
- # Gyro::Child
8
-
9
- `Gyro::Child` encapsulates a libev [child
10
- watcher](http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_ev_child_code_watch_out_for_pro),
11
- used for waiting for a child process to terminate. A `Gyro::Child` watcher
12
- instance can be used for low-level control of child processes, instead of using
13
- more high-level APIs such `Process.wait` etc.
14
-
15
- ## Instance methods
16
-
17
- ### #await → [pid, exitcode]
18
-
19
- Blocks the current thread until the watcher is signalled. The return value is an
20
- array containing the child's pid and the exit code.
21
-
22
- ```ruby
23
- pid = Polyphony.fork { sleep 1 }
24
- Gyro::Child.new(pid).await #=> [pid, 0]
25
- ```
26
-
27
- ### #initialize(pid)
28
-
29
- Initializes the watcher instance with the given pid
@@ -1,44 +0,0 @@
1
- ---
2
- layout: page
3
- title: Gyro::Queue
4
- parent: API Reference
5
- permalink: /api-reference/gyro-queue/
6
- ---
7
- # Gyro::Queue
8
-
9
- `Gyro::Queue` implements a polyphonic (fiber-aware) queue that can store 0 or
10
- more items of any data types. Adding an item to the queue never blocks.
11
- Retrieving an item from the queue will block if the queue is empty.
12
- `Gyro::Queue` is both fiber-safe and thread-safe. This means multiple fibers
13
- from multiple threads can concurrently interact with the same queue.
14
- `Gyro::Queue` is used pervasively across the Polyphony code base for
15
- synchronisation and fiber control.
16
-
17
- ## Instance methods
18
-
19
- ### #&lt;&lt;(object) → queue<br>#push(object) → queue
20
-
21
- Adds an item to the queue.
22
-
23
- ### #clear → queue
24
-
25
- Removes all items currently in the queue.
26
-
27
- ### #empty? → true or false
28
-
29
- Returns true if the queue is empty. Otherwise returns false.
30
-
31
- ### #initialize
32
-
33
- Initializes an empty queue.
34
-
35
- ### #shift → object<br>#pop → object
36
-
37
- Retrieves an item from the queue. If the queue is empty, `#shift` blocks until
38
- an item is added to the queue or until interrupted. Multiple fibers calling
39
- `#shift` are served in a first-ordered first-served manner.
40
-
41
- ### #shift_each → [*object]<br>#shift_each({ block }) → queue
42
-
43
- Removes and returns all items currently in the queue. If a block is given, it
44
- will be invoked for each item.
@@ -1,51 +0,0 @@
1
- ---
2
- layout: page
3
- title: Gyro::Timer
4
- parent: API Reference
5
- permalink: /api-reference/gyro-timer/
6
- ---
7
- # Gyro::Timer
8
-
9
- `Gyro::Timer` encapsulates a libev [timer
10
- watcher](http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_ev_timer_code_relative_and_opti),
11
- allowing waiting a certain amount of time before proceeding with an operation.
12
- Watchers can be either one-time timers or recurring timers. The Polyphony API
13
- provides various APIs that use timer watchers for timeouts, throttled
14
- operations, and sleeping.
15
-
16
- ## Instance methods
17
-
18
- ### #await → object
19
-
20
- Blocks the current thread until the timer has elapsed. For recurrent timers,
21
- `#await` will block until the next timer period has elapsed, as specified by the
22
- `repeat` argument given to `#initialize`.
23
-
24
- ### #initialize(after, repeat)
25
-
26
- Initializes the watcher instance. The `after` argument gives the time duration
27
- in seconds before the timer has elapsed. The `repeat` argument gives the time
28
- period for recurring timers, or `0` for non-recurring timers.
29
-
30
- ### #stop
31
-
32
- Stops an active recurring timer. Recurring timers stay active (from the point of
33
- view of the event loop) even after the timer period has elapsed. Calling `#stop`
34
- marks the timer as inactive and cleans up associated resources. This should
35
- normally be done inside an `ensure` block:
36
-
37
- ```ruby
38
- def repeat(period)
39
- timer = Gyro::Timer.new(period, period)
40
- loop do
41
- timer.await
42
- yield
43
- end
44
- ensure
45
- timer.stop
46
- end
47
-
48
- repeat(10) { puts Time.now }
49
- ```
50
-
51
- There's no need to call `#stop` for non-recurring timers.
@@ -1,25 +0,0 @@
1
- ---
2
- layout: page
3
- title: Gyro
4
- parent: API Reference
5
- permalink: /api-reference/gyro/
6
- ---
7
- # Gyro
8
-
9
- `Gyro` is the subsystem in charge of the low-level functionality in Polyphony.
10
- It contains all of the different event watcher classes, as well as other
11
- low-level constructs such as `Gyro::Queue`, a fiber-aware queue implementation,
12
- used pervasively across the Polyphony code base.
13
-
14
- While most Polyphony-based applications do not normally need to interact
15
- directly with the `Gyro` classes, more advanced applications and libraries may
16
- use those classes to enhance Polyphony and create custom concurrency patterns.
17
-
18
- ## Classes
19
-
20
- - [`Gyro::Async`](../gyro-async/) - async event watcher
21
- - [`Gyro::Child`](../gyro-child/) - child process event watcher
22
- - [`Gyro::IO`](../gyro-io/) - IO event watcher
23
- - [`Gyro::Queue`](../gyro-queue/) - fiber-aware queue
24
- - [`Gyro::Signal`](../gyro-signal/) - signal event watcher
25
- - [`Gyro::Timer`](../gyro-timer/) - timer event watcher
@@ -1,10 +0,0 @@
1
- ---
2
- layout: page
3
- title: Getting Started
4
- description: Lorem ipsum
5
- has_children: true
6
- section: true
7
- has_toc: false
8
- nav_order: 2
9
- section_link: /getting-started/installing
10
- ---