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.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Gemfile +1 -0
- data/README.md +1 -0
- data/Rakefile +15 -0
- data/doc/Gemfile.html +87 -0
- data/doc/README_md.html +85 -0
- data/doc/Yunhe/Consumer.html +194 -0
- data/doc/Yunhe/Core.html +396 -0
- data/doc/Yunhe/Producer.html +194 -0
- data/doc/Yunhe.html +164 -0
- data/doc/created.rid +9 -0
- data/doc/css/fonts.css +167 -0
- data/doc/css/rdoc.css +590 -0
- data/doc/fonts/Lato-Light.ttf +0 -0
- data/doc/fonts/Lato-LightItalic.ttf +0 -0
- data/doc/fonts/Lato-Regular.ttf +0 -0
- data/doc/fonts/Lato-RegularItalic.ttf +0 -0
- data/doc/fonts/SourceCodePro-Bold.ttf +0 -0
- data/doc/fonts/SourceCodePro-Regular.ttf +0 -0
- data/doc/images/add.png +0 -0
- data/doc/images/arrow_up.png +0 -0
- data/doc/images/brick.png +0 -0
- data/doc/images/brick_link.png +0 -0
- data/doc/images/bug.png +0 -0
- data/doc/images/bullet_black.png +0 -0
- data/doc/images/bullet_toggle_minus.png +0 -0
- data/doc/images/bullet_toggle_plus.png +0 -0
- data/doc/images/date.png +0 -0
- data/doc/images/delete.png +0 -0
- data/doc/images/find.png +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/macFFBgHack.png +0 -0
- data/doc/images/package.png +0 -0
- data/doc/images/page_green.png +0 -0
- data/doc/images/page_white_text.png +0 -0
- data/doc/images/page_white_width.png +0 -0
- data/doc/images/plugin.png +0 -0
- data/doc/images/ruby.png +0 -0
- data/doc/images/tag_blue.png +0 -0
- data/doc/images/tag_green.png +0 -0
- data/doc/images/transparent.png +0 -0
- data/doc/images/wrench.png +0 -0
- data/doc/images/wrench_orange.png +0 -0
- data/doc/images/zoom.png +0 -0
- data/doc/index.html +101 -0
- data/doc/js/darkfish.js +161 -0
- data/doc/js/jquery.js +4 -0
- data/doc/js/navigation.js +142 -0
- data/doc/js/navigation.js.gz +0 -0
- data/doc/js/search.js +109 -0
- data/doc/js/search_index.js +1 -0
- data/doc/js/search_index.js.gz +0 -0
- data/doc/js/searcher.js +228 -0
- data/doc/js/searcher.js.gz +0 -0
- data/doc/table_of_contents.html +101 -0
- data/doc/yunhe_gemspec.html +105 -0
- data/lib/yunhe/consumer.rb +24 -0
- data/lib/yunhe/core.rb +111 -0
- data/lib/yunhe/producer.rb +21 -0
- data/lib/yunhe/version.rb +3 -0
- data/lib/yunhe.rb +20 -0
- data/yunhe.gemspec +18 -0
- 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 &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 => 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 &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 'ruby.taobao.org'\n<p>gem 'minitest', :group => :test\n"],["README","","README_md.html","","<p>Yunhe\n"],["yunhe.gemspec","","yunhe_gemspec.html","","<p>$LOAD_PATH.push File.expand_path('../lib', __FILE__) require\n'yunhe/version'\n<p>Gem::Specification.new …\n"]]}}
|
|
Binary file
|
data/doc/js/searcher.js
ADDED
|
@@ -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
|
+
—
|
|
61
|
+
<span class="container">Yunhe::Consumer</span>
|
|
62
|
+
|
|
63
|
+
<li class="method">
|
|
64
|
+
<a href="Yunhe/Core.html#method-c-new">::new</a>
|
|
65
|
+
—
|
|
66
|
+
<span class="container">Yunhe::Core</span>
|
|
67
|
+
|
|
68
|
+
<li class="method">
|
|
69
|
+
<a href="Yunhe/Producer.html#method-c-new">::new</a>
|
|
70
|
+
—
|
|
71
|
+
<span class="container">Yunhe::Producer</span>
|
|
72
|
+
|
|
73
|
+
<li class="method">
|
|
74
|
+
<a href="Yunhe.html#method-i-build">#build</a>
|
|
75
|
+
—
|
|
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
|
+
—
|
|
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
|
+
—
|
|
86
|
+
<span class="container">Yunhe::Core</span>
|
|
87
|
+
|
|
88
|
+
<li class="method">
|
|
89
|
+
<a href="Yunhe/Core.html#method-i-terminate">#terminate</a>
|
|
90
|
+
—
|
|
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('../lib', __FILE__) require
|
|
76
|
+
'yunhe/version'</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">'yunhe'</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">'2015-03-31'</span>
|
|
83
|
+
<span class="ruby-identifier">s</span>.<span class="ruby-identifier">summary</span> = <span class="ruby-string">"Yunhe"</span>
|
|
84
|
+
<span class="ruby-identifier">s</span>.<span class="ruby-identifier">description</span> = <span class="ruby-string">"A light weight producer-consumer gem"</span>
|
|
85
|
+
<span class="ruby-identifier">s</span>.<span class="ruby-identifier">authors</span> = [<span class="ruby-string">"Karloku Sang"</span>]
|
|
86
|
+
<span class="ruby-identifier">s</span>.<span class="ruby-identifier">email</span> = <span class="ruby-string">'karloku@loku.it'</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">"\n"</span>)
|
|
88
|
+
<span class="ruby-identifier">s</span>.<span class="ruby-identifier">homepage</span> =
|
|
89
|
+
<span class="ruby-string">'http://loku.it/yunhe'</span>
|
|
90
|
+
<span class="ruby-identifier">s</span>.<span class="ruby-identifier">license</span> = <span class="ruby-string">'MIT'</span>
|
|
91
|
+
|
|
92
|
+
<span class="ruby-identifier">s</span>.<span class="ruby-identifier">rdoc_options</span> = [<span class="ruby-string">"--main"</span>, <span class="ruby-string">"README.md"</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
|