yunhe 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/Gemfile +1 -0
  4. data/README.md +1 -0
  5. data/Rakefile +15 -0
  6. data/doc/Gemfile.html +87 -0
  7. data/doc/README_md.html +85 -0
  8. data/doc/Yunhe/Consumer.html +194 -0
  9. data/doc/Yunhe/Core.html +396 -0
  10. data/doc/Yunhe/Producer.html +194 -0
  11. data/doc/Yunhe.html +164 -0
  12. data/doc/created.rid +9 -0
  13. data/doc/css/fonts.css +167 -0
  14. data/doc/css/rdoc.css +590 -0
  15. data/doc/fonts/Lato-Light.ttf +0 -0
  16. data/doc/fonts/Lato-LightItalic.ttf +0 -0
  17. data/doc/fonts/Lato-Regular.ttf +0 -0
  18. data/doc/fonts/Lato-RegularItalic.ttf +0 -0
  19. data/doc/fonts/SourceCodePro-Bold.ttf +0 -0
  20. data/doc/fonts/SourceCodePro-Regular.ttf +0 -0
  21. data/doc/images/add.png +0 -0
  22. data/doc/images/arrow_up.png +0 -0
  23. data/doc/images/brick.png +0 -0
  24. data/doc/images/brick_link.png +0 -0
  25. data/doc/images/bug.png +0 -0
  26. data/doc/images/bullet_black.png +0 -0
  27. data/doc/images/bullet_toggle_minus.png +0 -0
  28. data/doc/images/bullet_toggle_plus.png +0 -0
  29. data/doc/images/date.png +0 -0
  30. data/doc/images/delete.png +0 -0
  31. data/doc/images/find.png +0 -0
  32. data/doc/images/loadingAnimation.gif +0 -0
  33. data/doc/images/macFFBgHack.png +0 -0
  34. data/doc/images/package.png +0 -0
  35. data/doc/images/page_green.png +0 -0
  36. data/doc/images/page_white_text.png +0 -0
  37. data/doc/images/page_white_width.png +0 -0
  38. data/doc/images/plugin.png +0 -0
  39. data/doc/images/ruby.png +0 -0
  40. data/doc/images/tag_blue.png +0 -0
  41. data/doc/images/tag_green.png +0 -0
  42. data/doc/images/transparent.png +0 -0
  43. data/doc/images/wrench.png +0 -0
  44. data/doc/images/wrench_orange.png +0 -0
  45. data/doc/images/zoom.png +0 -0
  46. data/doc/index.html +101 -0
  47. data/doc/js/darkfish.js +161 -0
  48. data/doc/js/jquery.js +4 -0
  49. data/doc/js/navigation.js +142 -0
  50. data/doc/js/navigation.js.gz +0 -0
  51. data/doc/js/search.js +109 -0
  52. data/doc/js/search_index.js +1 -0
  53. data/doc/js/search_index.js.gz +0 -0
  54. data/doc/js/searcher.js +228 -0
  55. data/doc/js/searcher.js.gz +0 -0
  56. data/doc/table_of_contents.html +101 -0
  57. data/doc/yunhe_gemspec.html +105 -0
  58. data/lib/yunhe/consumer.rb +24 -0
  59. data/lib/yunhe/core.rb +111 -0
  60. data/lib/yunhe/producer.rb +21 -0
  61. data/lib/yunhe/version.rb +3 -0
  62. data/lib/yunhe.rb +20 -0
  63. data/yunhe.gemspec +18 -0
  64. metadata +107 -0
Binary file
data/doc/js/search.js ADDED
@@ -0,0 +1,109 @@
1
+ Search = function(data, input, result) {
2
+ this.data = data;
3
+ this.$input = $(input);
4
+ this.$result = $(result);
5
+
6
+ this.$current = null;
7
+ this.$view = this.$result.parent();
8
+ this.searcher = new Searcher(data.index);
9
+ this.init();
10
+ }
11
+
12
+ Search.prototype = $.extend({}, Navigation, new function() {
13
+ var suid = 1;
14
+
15
+ this.init = function() {
16
+ var _this = this;
17
+ var observer = function(e) {
18
+ switch(e.originalEvent.keyCode) {
19
+ case 38: // Event.KEY_UP
20
+ case 40: // Event.KEY_DOWN
21
+ return;
22
+ }
23
+ _this.search(_this.$input[0].value);
24
+ };
25
+ this.$input.keyup(observer);
26
+ this.$input.click(observer); // mac's clear field
27
+
28
+ this.searcher.ready(function(results, isLast) {
29
+ _this.addResults(results, isLast);
30
+ })
31
+
32
+ this.initNavigation();
33
+ this.setNavigationActive(false);
34
+ }
35
+
36
+ this.search = function(value, selectFirstMatch) {
37
+ value = jQuery.trim(value).toLowerCase();
38
+ if (value) {
39
+ this.setNavigationActive(true);
40
+ } else {
41
+ this.setNavigationActive(false);
42
+ }
43
+
44
+ if (value == '') {
45
+ this.lastQuery = value;
46
+ this.$result.empty();
47
+ this.$result.attr('aria-expanded', 'false');
48
+ this.setNavigationActive(false);
49
+ } else if (value != this.lastQuery) {
50
+ this.lastQuery = value;
51
+ this.$result.attr('aria-busy', 'true');
52
+ this.$result.attr('aria-expanded', 'true');
53
+ this.firstRun = true;
54
+ this.searcher.find(value);
55
+ }
56
+ }
57
+
58
+ this.addResults = function(results, isLast) {
59
+ var target = this.$result.get(0);
60
+ if (this.firstRun && (results.length > 0 || isLast)) {
61
+ this.$current = null;
62
+ this.$result.empty();
63
+ }
64
+
65
+ for (var i=0, l = results.length; i < l; i++) {
66
+ var item = this.renderItem.call(this, results[i]);
67
+ item.setAttribute('id', 'search-result-' + target.childElementCount);
68
+ target.appendChild(item);
69
+ };
70
+
71
+ if (this.firstRun && results.length > 0) {
72
+ this.firstRun = false;
73
+ this.$current = $(target.firstChild);
74
+ this.$current.addClass('search-selected');
75
+ }
76
+ if (jQuery.browser.msie) this.$element[0].className += '';
77
+
78
+ if (isLast) this.$result.attr('aria-busy', 'false');
79
+ }
80
+
81
+ this.move = function(isDown) {
82
+ if (!this.$current) return;
83
+ var $next = this.$current[isDown ? 'next' : 'prev']();
84
+ if ($next.length) {
85
+ this.$current.removeClass('search-selected');
86
+ $next.addClass('search-selected');
87
+ this.$input.attr('aria-activedescendant', $next.attr('id'));
88
+ this.scrollIntoView($next[0], this.$view[0]);
89
+ this.$current = $next;
90
+ this.$input.val($next[0].firstChild.firstChild.text);
91
+ this.$input.select();
92
+ }
93
+ return true;
94
+ }
95
+
96
+ this.hlt = function(html) {
97
+ return this.escapeHTML(html).
98
+ replace(/\u0001/g, '<em>').
99
+ replace(/\u0002/g, '</em>');
100
+ }
101
+
102
+ this.escapeHTML = function(html) {
103
+ return html.replace(/[&<>]/g, function(c) {
104
+ return '&#' + c.charCodeAt(0) + ';';
105
+ });
106
+ }
107
+
108
+ });
109
+
@@ -0,0 +1 @@
1
+ var search_data = {"index":{"searchIndex":["yunhe","consumer","core","producer","build()","consume_with()","new()","new()","new()","produce_by()","terminate()","gemfile","readme","yunhe.gemspec"],"longSearchIndex":["yunhe","yunhe::consumer","yunhe::core","yunhe::producer","yunhe#build()","yunhe::core#consume_with()","yunhe::consumer::new()","yunhe::core::new()","yunhe::producer::new()","yunhe::core#produce_by()","yunhe::core#terminate()","","",""],"info":[["Yunhe","","Yunhe.html","",""],["Yunhe::Consumer","","Yunhe/Consumer.html","",""],["Yunhe::Core","","Yunhe/Core.html","","<p>The core class that manages the producers and consumers.\n"],["Yunhe::Producer","","Yunhe/Producer.html","",""],["build","Yunhe","Yunhe.html#method-i-build","(options={})",""],["consume_with","Yunhe::Core","Yunhe/Core.html#method-i-consume_with","(&task)","<p>Set the consumer task &amp;task: The task that procceed the resources.\nShould take the resource as a …\n"],["new","Yunhe::Consumer","Yunhe/Consumer.html#method-c-new","(queue, block)",""],["new","Yunhe::Core","Yunhe/Core.html#method-c-new","(options)","<p>Initialize a new yunhe core with options: :producer_size =&gt; Size of\nthe producer pool :consumer_size …\n"],["new","Yunhe::Producer","Yunhe/Producer.html#method-c-new","(queue, block)",""],["produce_by","Yunhe::Core","Yunhe/Core.html#method-i-produce_by","(&task)","<p>Set the producer task &amp;task: The task that produces a new resource.\nShould have the resource returned: …\n"],["terminate","Yunhe::Core","Yunhe/Core.html#method-i-terminate","()","<p>Stop the yunhe core. Kill all producer/consumer threads, and clear the\nbuffer queue.\n"],["Gemfile","","Gemfile.html","","<p>source &#39;ruby.taobao.org&#39;\n<p>gem &#39;minitest&#39;, :group =&gt; :test\n"],["README","","README_md.html","","<p>Yunhe\n"],["yunhe.gemspec","","yunhe_gemspec.html","","<p>$LOAD_PATH.push File.expand_path(&#39;../lib&#39;, __FILE__) require\n&#39;yunhe/version&#39;\n<p>Gem::Specification.new …\n"]]}}
Binary file
@@ -0,0 +1,228 @@
1
+ Searcher = function(data) {
2
+ this.data = data;
3
+ this.handlers = [];
4
+ }
5
+
6
+ Searcher.prototype = new function() {
7
+ // search is performed in chunks of 1000 for non-blocking user input
8
+ var CHUNK_SIZE = 1000;
9
+ // do not try to find more than 100 results
10
+ var MAX_RESULTS = 100;
11
+ var huid = 1;
12
+ var suid = 1;
13
+ var runs = 0;
14
+
15
+ this.find = function(query) {
16
+ var queries = splitQuery(query);
17
+ var regexps = buildRegexps(queries);
18
+ var highlighters = buildHilighters(queries);
19
+ var state = { from: 0, pass: 0, limit: MAX_RESULTS, n: suid++};
20
+ var _this = this;
21
+
22
+ this.currentSuid = state.n;
23
+
24
+ if (!query) return;
25
+
26
+ var run = function() {
27
+ // stop current search thread if new search started
28
+ if (state.n != _this.currentSuid) return;
29
+
30
+ var results =
31
+ performSearch(_this.data, regexps, queries, highlighters, state);
32
+ var hasMore = (state.limit > 0 && state.pass < 4);
33
+
34
+ triggerResults.call(_this, results, !hasMore);
35
+ if (hasMore) {
36
+ setTimeout(run, 2);
37
+ }
38
+ runs++;
39
+ };
40
+ runs = 0;
41
+
42
+ // start search thread
43
+ run();
44
+ }
45
+
46
+ /* ----- Events ------ */
47
+ this.ready = function(fn) {
48
+ fn.huid = huid;
49
+ this.handlers.push(fn);
50
+ }
51
+
52
+ /* ----- Utilities ------ */
53
+ function splitQuery(query) {
54
+ return jQuery.grep(query.split(/(\s+|::?|\(\)?)/), function(string) {
55
+ return string.match(/\S/)
56
+ });
57
+ }
58
+
59
+ function buildRegexps(queries) {
60
+ return jQuery.map(queries, function(query) {
61
+ return new RegExp(query.replace(/(.)/g, '([$1])([^$1]*?)'), 'i')
62
+ });
63
+ }
64
+
65
+ function buildHilighters(queries) {
66
+ return jQuery.map(queries, function(query) {
67
+ return jQuery.map(query.split(''), function(l, i) {
68
+ return '\u0001$' + (i*2+1) + '\u0002$' + (i*2+2);
69
+ }).join('');
70
+ });
71
+ }
72
+
73
+ // function longMatchRegexp(index, longIndex, regexps) {
74
+ // for (var i = regexps.length - 1; i >= 0; i--){
75
+ // if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
76
+ // };
77
+ // return true;
78
+ // }
79
+
80
+
81
+ /* ----- Mathchers ------ */
82
+
83
+ /*
84
+ * This record matches if the index starts with queries[0] and the record
85
+ * matches all of the regexps
86
+ */
87
+ function matchPassBeginning(index, longIndex, queries, regexps) {
88
+ if (index.indexOf(queries[0]) != 0) return false;
89
+ for (var i=1, l = regexps.length; i < l; i++) {
90
+ if (!index.match(regexps[i]) && !longIndex.match(regexps[i]))
91
+ return false;
92
+ };
93
+ return true;
94
+ }
95
+
96
+ /*
97
+ * This record matches if the longIndex starts with queries[0] and the
98
+ * longIndex matches all of the regexps
99
+ */
100
+ function matchPassLongIndex(index, longIndex, queries, regexps) {
101
+ if (longIndex.indexOf(queries[0]) != 0) return false;
102
+ for (var i=1, l = regexps.length; i < l; i++) {
103
+ if (!longIndex.match(regexps[i]))
104
+ return false;
105
+ };
106
+ return true;
107
+ }
108
+
109
+ /*
110
+ * This record matches if the index contains queries[0] and the record
111
+ * matches all of the regexps
112
+ */
113
+ function matchPassContains(index, longIndex, queries, regexps) {
114
+ if (index.indexOf(queries[0]) == -1) return false;
115
+ for (var i=1, l = regexps.length; i < l; i++) {
116
+ if (!index.match(regexps[i]) && !longIndex.match(regexps[i]))
117
+ return false;
118
+ };
119
+ return true;
120
+ }
121
+
122
+ /*
123
+ * This record matches if regexps[0] matches the index and the record
124
+ * matches all of the regexps
125
+ */
126
+ function matchPassRegexp(index, longIndex, queries, regexps) {
127
+ if (!index.match(regexps[0])) return false;
128
+ for (var i=1, l = regexps.length; i < l; i++) {
129
+ if (!index.match(regexps[i]) && !longIndex.match(regexps[i]))
130
+ return false;
131
+ };
132
+ return true;
133
+ }
134
+
135
+
136
+ /* ----- Highlighters ------ */
137
+ function highlightRegexp(info, queries, regexps, highlighters) {
138
+ var result = createResult(info);
139
+ for (var i=0, l = regexps.length; i < l; i++) {
140
+ result.title = result.title.replace(regexps[i], highlighters[i]);
141
+ result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
142
+ };
143
+ return result;
144
+ }
145
+
146
+ function hltSubstring(string, pos, length) {
147
+ return string.substring(0, pos) + '\u0001' + string.substring(pos, pos + length) + '\u0002' + string.substring(pos + length);
148
+ }
149
+
150
+ function highlightQuery(info, queries, regexps, highlighters) {
151
+ var result = createResult(info);
152
+ var pos = 0;
153
+ var lcTitle = result.title.toLowerCase();
154
+
155
+ pos = lcTitle.indexOf(queries[0]);
156
+ if (pos != -1) {
157
+ result.title = hltSubstring(result.title, pos, queries[0].length);
158
+ }
159
+
160
+ result.namespace = result.namespace.replace(regexps[0], highlighters[0]);
161
+ for (var i=1, l = regexps.length; i < l; i++) {
162
+ result.title = result.title.replace(regexps[i], highlighters[i]);
163
+ result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
164
+ };
165
+ return result;
166
+ }
167
+
168
+ function createResult(info) {
169
+ var result = {};
170
+ result.title = info[0];
171
+ result.namespace = info[1];
172
+ result.path = info[2];
173
+ result.params = info[3];
174
+ result.snippet = info[4];
175
+ return result;
176
+ }
177
+
178
+ /* ----- Searching ------ */
179
+ function performSearch(data, regexps, queries, highlighters, state) {
180
+ var searchIndex = data.searchIndex;
181
+ var longSearchIndex = data.longSearchIndex;
182
+ var info = data.info;
183
+ var result = [];
184
+ var i = state.from;
185
+ var l = searchIndex.length;
186
+ var togo = CHUNK_SIZE;
187
+ var matchFunc, hltFunc;
188
+
189
+ while (state.pass < 4 && state.limit > 0 && togo > 0) {
190
+ if (state.pass == 0) {
191
+ matchFunc = matchPassBeginning;
192
+ hltFunc = highlightQuery;
193
+ } else if (state.pass == 1) {
194
+ matchFunc = matchPassLongIndex;
195
+ hltFunc = highlightQuery;
196
+ } else if (state.pass == 2) {
197
+ matchFunc = matchPassContains;
198
+ hltFunc = highlightQuery;
199
+ } else if (state.pass == 3) {
200
+ matchFunc = matchPassRegexp;
201
+ hltFunc = highlightRegexp;
202
+ }
203
+
204
+ for (; togo > 0 && i < l && state.limit > 0; i++, togo--) {
205
+ if (info[i].n == state.n) continue;
206
+ if (matchFunc(searchIndex[i], longSearchIndex[i], queries, regexps)) {
207
+ info[i].n = state.n;
208
+ result.push(hltFunc(info[i], queries, regexps, highlighters));
209
+ state.limit--;
210
+ }
211
+ };
212
+ if (searchIndex.length <= i) {
213
+ state.pass++;
214
+ i = state.from = 0;
215
+ } else {
216
+ state.from = i;
217
+ }
218
+ }
219
+ return result;
220
+ }
221
+
222
+ function triggerResults(results, isLast) {
223
+ jQuery.each(this.handlers, function(i, fn) {
224
+ fn.call(this, results, isLast)
225
+ })
226
+ }
227
+ }
228
+
Binary file
@@ -0,0 +1,101 @@
1
+ <!DOCTYPE html>
2
+
3
+ <html>
4
+ <head>
5
+ <meta charset="UTF-8">
6
+
7
+ <title>Table of Contents - RDoc Documentation</title>
8
+
9
+ <script type="text/javascript">
10
+ var rdoc_rel_prefix = "./";
11
+ </script>
12
+
13
+ <script src="./js/jquery.js"></script>
14
+ <script src="./js/darkfish.js"></script>
15
+
16
+ <link href="./css/fonts.css" rel="stylesheet">
17
+ <link href="./css/rdoc.css" rel="stylesheet">
18
+
19
+
20
+
21
+ <body id="top" class="table-of-contents">
22
+ <main role="main">
23
+ <h1 class="class">Table of Contents - RDoc Documentation</h1>
24
+
25
+ <h2 id="pages">Pages</h2>
26
+ <ul>
27
+ <li class="file">
28
+ <a href="Gemfile.html">Gemfile</a>
29
+ </li>
30
+ <li class="file">
31
+ <a href="README_md.html">README</a>
32
+ </li>
33
+ <li class="file">
34
+ <a href="yunhe_gemspec.html">yunhe.gemspec</a>
35
+ </li>
36
+
37
+ </ul>
38
+
39
+ <h2 id="classes">Classes and Modules</h2>
40
+ <ul>
41
+ <li class="module">
42
+ <a href="Yunhe.html">Yunhe</a>
43
+ </li>
44
+ <li class="class">
45
+ <a href="Yunhe/Consumer.html">Yunhe::Consumer</a>
46
+ </li>
47
+ <li class="class">
48
+ <a href="Yunhe/Core.html">Yunhe::Core</a>
49
+ </li>
50
+ <li class="class">
51
+ <a href="Yunhe/Producer.html">Yunhe::Producer</a>
52
+ </li>
53
+ </ul>
54
+
55
+ <h2 id="methods">Methods</h2>
56
+ <ul>
57
+
58
+ <li class="method">
59
+ <a href="Yunhe/Consumer.html#method-c-new">::new</a>
60
+ &mdash;
61
+ <span class="container">Yunhe::Consumer</span>
62
+
63
+ <li class="method">
64
+ <a href="Yunhe/Core.html#method-c-new">::new</a>
65
+ &mdash;
66
+ <span class="container">Yunhe::Core</span>
67
+
68
+ <li class="method">
69
+ <a href="Yunhe/Producer.html#method-c-new">::new</a>
70
+ &mdash;
71
+ <span class="container">Yunhe::Producer</span>
72
+
73
+ <li class="method">
74
+ <a href="Yunhe.html#method-i-build">#build</a>
75
+ &mdash;
76
+ <span class="container">Yunhe</span>
77
+
78
+ <li class="method">
79
+ <a href="Yunhe/Core.html#method-i-consume_with">#consume_with</a>
80
+ &mdash;
81
+ <span class="container">Yunhe::Core</span>
82
+
83
+ <li class="method">
84
+ <a href="Yunhe/Core.html#method-i-produce_by">#produce_by</a>
85
+ &mdash;
86
+ <span class="container">Yunhe::Core</span>
87
+
88
+ <li class="method">
89
+ <a href="Yunhe/Core.html#method-i-terminate">#terminate</a>
90
+ &mdash;
91
+ <span class="container">Yunhe::Core</span>
92
+ </ul>
93
+ </main>
94
+
95
+
96
+ <footer id="validator-badges" role="contentinfo">
97
+ <p><a href="http://validator.w3.org/check/referer">Validate</a>
98
+ <p>Generated by <a href="http://docs.seattlerb.org/rdoc/">RDoc</a> 4.2.0.
99
+ <p>Based on <a href="http://deveiate.org/projects/Darkfish-RDoc/">Darkfish</a> by <a href="http://deveiate.org">Michael Granger</a>.
100
+ </footer>
101
+
@@ -0,0 +1,105 @@
1
+ <!DOCTYPE html>
2
+
3
+ <html>
4
+ <head>
5
+ <meta charset="UTF-8">
6
+
7
+ <title>yunhe.gemspec - RDoc Documentation</title>
8
+
9
+ <script type="text/javascript">
10
+ var rdoc_rel_prefix = "./";
11
+ </script>
12
+
13
+ <script src="./js/jquery.js"></script>
14
+ <script src="./js/darkfish.js"></script>
15
+
16
+ <link href="./css/fonts.css" rel="stylesheet">
17
+ <link href="./css/rdoc.css" rel="stylesheet">
18
+
19
+
20
+
21
+ <body id="top" role="document" class="file">
22
+ <nav role="navigation">
23
+ <div id="project-navigation">
24
+ <div id="home-section" role="region" title="Quick navigation" class="nav-section">
25
+ <h2>
26
+ <a href="./index.html" rel="home">Home</a>
27
+ </h2>
28
+
29
+ <div id="table-of-contents-navigation">
30
+ <a href="./table_of_contents.html#pages">Pages</a>
31
+ <a href="./table_of_contents.html#classes">Classes</a>
32
+ <a href="./table_of_contents.html#methods">Methods</a>
33
+ </div>
34
+ </div>
35
+
36
+ <div id="search-section" role="search" class="project-section initially-hidden">
37
+ <form action="#" method="get" accept-charset="utf-8">
38
+ <div id="search-field-wrapper">
39
+ <input id="search-field" role="combobox" aria-label="Search"
40
+ aria-autocomplete="list" aria-controls="search-results"
41
+ type="text" name="search" placeholder="Search" spellcheck="false"
42
+ title="Type to search, Up and Down to navigate, Enter to load">
43
+ </div>
44
+
45
+ <ul id="search-results" aria-label="Search Results"
46
+ aria-busy="false" aria-expanded="false"
47
+ aria-atomic="false" class="initially-hidden"></ul>
48
+ </form>
49
+ </div>
50
+
51
+ </div>
52
+
53
+
54
+
55
+ <div id="project-metadata">
56
+ <div id="fileindex-section" class="nav-section">
57
+ <h3>Pages</h3>
58
+
59
+ <ul class="link-list">
60
+
61
+ <li><a href="./Gemfile.html">Gemfile</a>
62
+
63
+ <li><a href="./README_md.html">README</a>
64
+
65
+ <li><a href="./yunhe_gemspec.html">yunhe.gemspec</a>
66
+
67
+ </ul>
68
+ </div>
69
+
70
+ </div>
71
+ </nav>
72
+
73
+ <main role="main" aria-label="Page yunhe.gemspec">
74
+
75
+ <p>$LOAD_PATH.push File.expand_path(&#39;../lib&#39;, __FILE__) require
76
+ &#39;yunhe/version&#39;</p>
77
+
78
+ <p>Gem::Specification.new do |s|</p>
79
+
80
+ <pre class="ruby"><span class="ruby-identifier">s</span>.<span class="ruby-identifier">name</span> = <span class="ruby-string">&#39;yunhe&#39;</span>
81
+ <span class="ruby-identifier">s</span>.<span class="ruby-identifier">version</span> = <span class="ruby-constant">Yunhe</span><span class="ruby-operator">::</span><span class="ruby-constant">VERSION</span>
82
+ <span class="ruby-identifier">s</span>.<span class="ruby-identifier">date</span> = <span class="ruby-string">&#39;2015-03-31&#39;</span>
83
+ <span class="ruby-identifier">s</span>.<span class="ruby-identifier">summary</span> = <span class="ruby-string">&quot;Yunhe&quot;</span>
84
+ <span class="ruby-identifier">s</span>.<span class="ruby-identifier">description</span> = <span class="ruby-string">&quot;A light weight producer-consumer gem&quot;</span>
85
+ <span class="ruby-identifier">s</span>.<span class="ruby-identifier">authors</span> = [<span class="ruby-string">&quot;Karloku Sang&quot;</span>]
86
+ <span class="ruby-identifier">s</span>.<span class="ruby-identifier">email</span> = <span class="ruby-string">&#39;karloku@loku.it&#39;</span>
87
+ <span class="ruby-identifier">s</span>.<span class="ruby-identifier">files</span> = <span class="ruby-value">%x`git ls-files`</span>.<span class="ruby-identifier">split</span>(<span class="ruby-string">&quot;\n&quot;</span>)
88
+ <span class="ruby-identifier">s</span>.<span class="ruby-identifier">homepage</span> =
89
+ <span class="ruby-string">&#39;http://loku.it/yunhe&#39;</span>
90
+ <span class="ruby-identifier">s</span>.<span class="ruby-identifier">license</span> = <span class="ruby-string">&#39;MIT&#39;</span>
91
+
92
+ <span class="ruby-identifier">s</span>.<span class="ruby-identifier">rdoc_options</span> = [<span class="ruby-string">&quot;--main&quot;</span>, <span class="ruby-string">&quot;README.md&quot;</span>]
93
+ </pre>
94
+
95
+ <p>end</p>
96
+ </main>
97
+
98
+
99
+
100
+ <footer id="validator-badges" role="contentinfo">
101
+ <p><a href="http://validator.w3.org/check/referer">Validate</a>
102
+ <p>Generated by <a href="http://docs.seattlerb.org/rdoc/">RDoc</a> 4.2.0.
103
+ <p>Based on <a href="http://deveiate.org/projects/Darkfish-RDoc/">Darkfish</a> by <a href="http://deveiate.org">Michael Granger</a>.
104
+ </footer>
105
+
@@ -0,0 +1,24 @@
1
+ module Yunhe
2
+ class Consumer < Thread
3
+ attr_accessor :queue
4
+ attr_accessor :block
5
+
6
+ ##
7
+ # Initialize a new consumer
8
+ # queue: the reference of the buffer queue
9
+ # block: the task to process the resource
10
+ def initialize(queue, block)
11
+ super &(method(:job).to_proc)
12
+ @block = block
13
+ self.queue = queue
14
+ end
15
+
16
+ private
17
+ def job
18
+ while(true) do
19
+ ele = queue.deq
20
+ block.call(ele)
21
+ end
22
+ end
23
+ end
24
+ end
data/lib/yunhe/core.rb ADDED
@@ -0,0 +1,111 @@
1
+ module Yunhe
2
+ autoload :Producer, 'yunhe/producer'
3
+ autoload :Consumer, 'yunhe/consumer'
4
+
5
+ ##
6
+ # The core class that manages the producers and consumers.
7
+
8
+ class Core
9
+ attr_reader :producer_pool, :consumer_pool
10
+ attr_reader :queue
11
+ attr_accessor :producer_size, :consumer_size, :queue_size
12
+
13
+ ##
14
+ # Initialize a new yunhe core with options:
15
+ # :producer_size => Size of the producer pool
16
+ # :consumer_size => Size of the consumer pool
17
+ # :queue_size => Size of the buffer queue
18
+ def initialize(options)
19
+ @producer_size = options[:producer_size]
20
+ @consumer_size = options[:consumer_size]
21
+ @queue_size = options[:queue_size]
22
+
23
+ @producer_pool = ThreadGroup.new
24
+ @consumer_pool = ThreadGroup.new
25
+ @queue = SizedQueue.new(queue_size)
26
+ end
27
+
28
+ # readers
29
+
30
+ ##
31
+ # Get the producer pool
32
+ def producer_pool
33
+ @producer_pool = ThreadGroup.new unless @producer_pool
34
+ @producer_pool
35
+ end
36
+
37
+ ##
38
+ # Get the consumer pool
39
+ def consumer_pool
40
+ @consumer_pool = ThreadGroup.new unless @consumer_pool
41
+ @consumer_pool
42
+ end
43
+
44
+ ##
45
+ # Get the buffer queue
46
+
47
+ def queue
48
+ @queue = SizedQueue.new(@queue_size) unless @queue
49
+ @queue
50
+ end
51
+
52
+ # producer/consumer task setters
53
+
54
+ ##
55
+ # Set the producer task
56
+ # &task: The task that produces a new resource. Should have the resource returned:
57
+ # do
58
+ # ...
59
+ # return resource
60
+ # end
61
+ def produce_by (&task)
62
+ each_producer do | thread |
63
+ thread.kill
64
+ end
65
+
66
+ producer_size.times do
67
+ thread = Producer.new(queue, task)
68
+ producer_pool.add(thread)
69
+ end
70
+ end
71
+
72
+ ##
73
+ # Set the consumer task
74
+ # &task: The task that process the resources. Should take the resource as a paramater:
75
+ # do | resource |
76
+ # ...
77
+ # end
78
+ def consume_with (&task)
79
+ each_consumer do | thread |
80
+ thread.kill
81
+ end
82
+
83
+ consumer_size.times do
84
+ thread = Consumer.new(queue, task)
85
+ consumer_pool.add(thread)
86
+ end
87
+ end
88
+
89
+ ## Stop the yunhe core. Kill all producer/consumer threads, and clear the buffer queue.
90
+ def terminate
91
+ each_producer do | thread |
92
+ thread.kill
93
+ end
94
+
95
+ each_consumer do | thread |
96
+ thread.kill
97
+ end
98
+
99
+ queue.clear
100
+ end
101
+
102
+ private
103
+ def each_producer(&block)
104
+ producer_pool.list.each &block if producer_pool
105
+ end
106
+
107
+ def each_consumer(&block)
108
+ consumer_pool.list.each &block if consumer_pool
109
+ end
110
+ end
111
+ end