utilrb 0.2.3 → 1.0
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.
- data/Changes.txt +24 -0
- data/Manifest.txt +7 -3
- data/Rakefile +24 -1
- data/ext/faster.cc +57 -0
- data/ext/ruby_internals.h +72 -0
- data/ext/swap.cc +1 -35
- data/ext/value_set.cc +50 -11
- data/lib/utilrb/array/to_s.rb +2 -2
- data/lib/utilrb/common.rb +1 -1
- data/lib/utilrb/enumerable/sequence.rb +11 -3
- data/lib/utilrb/exception/full_message.rb +35 -3
- data/lib/utilrb/module/ancestor_p.rb +21 -2
- data/lib/utilrb/module/attr_predicate.rb +17 -0
- data/lib/utilrb/pkgconfig.rb +48 -0
- data/lib/utilrb/time/to_hms.rb +3 -3
- data/lib/utilrb/value_set.rb +18 -2
- data/test/data/test_pkgconfig.pc +9 -0
- data/test/test_enumerable.rb +12 -1
- data/test/test_exception.rb +38 -0
- data/test/test_module.rb +20 -0
- data/test/test_object.rb +19 -0
- data/test/test_pkgconfig.rb +35 -0
- data/test/test_proc.rb +28 -0
- metadata +14 -7
- data/lib/utilrb/queue/get.rb +0 -22
- data/lib/utilrb/queue.rb +0 -2
- data/patches/fastthread-queue-get.patch +0 -72
data/Changes.txt
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
=== Version 1.0
|
2
|
+
Bumped version number because of incompatible changes. Make it 1.0 since
|
3
|
+
having 0. version numbers for this kind of library is completely meaningless
|
4
|
+
|
5
|
+
* incompatible changes:
|
6
|
+
- Enumerable#+ acts on too many objects. Define it only on Enumerable::Enumerator
|
7
|
+
- remove automatic convertion into ValueSet for methods which were doing it
|
8
|
+
- removed Queue#get: fastthread is now the preferred threading library in
|
9
|
+
Ruby 1.8.6, so Queue#get cannot be implemented anymore
|
10
|
+
|
11
|
+
* new features:
|
12
|
+
- PkgConfig class
|
13
|
+
- define Proc#same_body?, Proc#file and Proc#line
|
14
|
+
- Module#attr_predicate
|
15
|
+
- 'since', 'until' and block parameters for Exception#full_message
|
16
|
+
- ValueSet#intersects? (more efficient than checking that the intersection
|
17
|
+
is empty)
|
18
|
+
|
19
|
+
* changes and fixes:
|
20
|
+
- properly handle singleton classes in has_ancestor?
|
21
|
+
- properly handle recursion in ValueSet#to_s and Array#to_s
|
22
|
+
- add the 'setup' task on the Rakefile to build the C extension
|
23
|
+
- make Module#has_ancestor? work event if the C extension is not built
|
24
|
+
|
1
25
|
=== Version 0.2.3
|
2
26
|
|
3
27
|
* new features:
|
data/Manifest.txt
CHANGED
@@ -7,6 +7,7 @@ bm/allocation.rb
|
|
7
7
|
bm/speed.rb
|
8
8
|
ext/extconf.rb
|
9
9
|
ext/faster.cc
|
10
|
+
ext/ruby_internals.h
|
10
11
|
ext/swap.cc
|
11
12
|
ext/value_set.cc
|
12
13
|
lib/utilrb.rb
|
@@ -38,6 +39,7 @@ lib/utilrb/logger/hierarchy.rb
|
|
38
39
|
lib/utilrb/module.rb
|
39
40
|
lib/utilrb/module/ancestor_p.rb
|
40
41
|
lib/utilrb/module/attr_enumerable.rb
|
42
|
+
lib/utilrb/module/attr_predicate.rb
|
41
43
|
lib/utilrb/module/define_method.rb
|
42
44
|
lib/utilrb/module/include.rb
|
43
45
|
lib/utilrb/module/inherited_enumerable.rb
|
@@ -46,8 +48,7 @@ lib/utilrb/object/address.rb
|
|
46
48
|
lib/utilrb/object/attribute.rb
|
47
49
|
lib/utilrb/object/singleton_class.rb
|
48
50
|
lib/utilrb/objectstats.rb
|
49
|
-
lib/utilrb/
|
50
|
-
lib/utilrb/queue/get.rb
|
51
|
+
lib/utilrb/pkgconfig.rb
|
51
52
|
lib/utilrb/set.rb
|
52
53
|
lib/utilrb/set/to_s.rb
|
53
54
|
lib/utilrb/time.rb
|
@@ -55,10 +56,11 @@ lib/utilrb/time/to_hms.rb
|
|
55
56
|
lib/utilrb/unbound_method.rb
|
56
57
|
lib/utilrb/unbound_method/call.rb
|
57
58
|
lib/utilrb/value_set.rb
|
58
|
-
|
59
|
+
test/data/test_pkgconfig.pc
|
59
60
|
test/test_array.rb
|
60
61
|
test/test_config.rb
|
61
62
|
test/test_enumerable.rb
|
63
|
+
test/test_exception.rb
|
62
64
|
test/test_gc.rb
|
63
65
|
test/test_hash.rb
|
64
66
|
test/test_kernel.rb
|
@@ -66,5 +68,7 @@ test/test_misc.rb
|
|
66
68
|
test/test_module.rb
|
67
69
|
test/test_object.rb
|
68
70
|
test/test_objectstats.rb
|
71
|
+
test/test_pkgconfig.rb
|
72
|
+
test/test_proc.rb
|
69
73
|
test/test_time.rb
|
70
74
|
test/test_unbound_method.rb
|
data/Rakefile
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
# FIX: Hoe always calls rdoc with -d, and diagram generation fails here
|
4
|
+
class Rake::RDocTask
|
5
|
+
alias __option_list__ option_list
|
6
|
+
def option_list
|
7
|
+
options = __option_list__
|
8
|
+
options.delete("-d")
|
9
|
+
options
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
1
13
|
require 'hoe'
|
2
14
|
require './lib/utilrb/common'
|
3
15
|
|
@@ -8,9 +20,20 @@ Hoe.new('utilrb', Utilrb::VERSION) do |p|
|
|
8
20
|
p.summary = 'Yet another Ruby toolkit'
|
9
21
|
p.description = p.paragraphs_of('README.txt', 3..6).join("\n\n")
|
10
22
|
p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
|
11
|
-
p.changes = p.paragraphs_of('Changes.txt', 0..
|
23
|
+
p.changes = p.paragraphs_of('Changes.txt', 0..3).join("\n\n")
|
12
24
|
|
13
25
|
p.extra_deps << 'facets'
|
26
|
+
p.rdoc_pattern = /(ext\/.*cc$|lib)|txt/
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "builds Utilrb's C extension"
|
30
|
+
task :setup do
|
31
|
+
Dir.chdir("ext") do
|
32
|
+
if !system("ruby extconf.rb") || !system("make")
|
33
|
+
raise "cannot build the C extension"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
FileUtils.ln_sf "../../ext/faster.so", "lib/utilrb/faster.so"
|
14
37
|
end
|
15
38
|
|
16
39
|
task :full_test do
|
data/ext/faster.cc
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
#include <set>
|
3
|
+
#include "ruby_internals.h"
|
3
4
|
|
4
5
|
using namespace std;
|
5
6
|
|
@@ -38,6 +39,59 @@ static VALUE kernel_is_singleton_p(VALUE self)
|
|
38
39
|
return Qfalse;
|
39
40
|
}
|
40
41
|
|
42
|
+
|
43
|
+
/* call-seq:
|
44
|
+
* proc.same_body?(other) => true or false
|
45
|
+
*
|
46
|
+
* Returns true if +self+ and +other+ have the same body
|
47
|
+
*/
|
48
|
+
static VALUE proc_same_body_p(VALUE self, VALUE other)
|
49
|
+
{
|
50
|
+
if (self == other) return Qtrue;
|
51
|
+
if (TYPE(other) != T_DATA) return Qfalse;
|
52
|
+
if (RDATA(other)->dmark != RDATA(self)->dmark) return Qfalse;
|
53
|
+
if (CLASS_OF(self) != CLASS_OF(other)) return Qfalse;
|
54
|
+
|
55
|
+
struct BLOCK* data, *data2;
|
56
|
+
Data_Get_Struct(self, struct BLOCK, data);
|
57
|
+
Data_Get_Struct(other, struct BLOCK, data2);
|
58
|
+
return (data->body == data2->body) ? Qtrue : Qfalse;
|
59
|
+
}
|
60
|
+
|
61
|
+
/* call-seq:
|
62
|
+
* proc.file
|
63
|
+
*
|
64
|
+
* Returns the file in which the proc body is defined, or nil
|
65
|
+
*/
|
66
|
+
static VALUE proc_file(VALUE self)
|
67
|
+
{
|
68
|
+
struct BLOCK *data;
|
69
|
+
NODE *node;
|
70
|
+
|
71
|
+
Data_Get_Struct(self, struct BLOCK, data);
|
72
|
+
if ((node = data->frame.node) || (node = data->body))
|
73
|
+
return rb_str_new2(node->nd_file);
|
74
|
+
else
|
75
|
+
return Qnil;
|
76
|
+
}
|
77
|
+
|
78
|
+
/* call-seq:
|
79
|
+
* proc.file
|
80
|
+
*
|
81
|
+
* Returns the line at which the proc body is defined, or nil
|
82
|
+
*/
|
83
|
+
static VALUE proc_line(VALUE self)
|
84
|
+
{
|
85
|
+
struct BLOCK *data;
|
86
|
+
NODE *node;
|
87
|
+
|
88
|
+
Data_Get_Struct(self, struct BLOCK, data);
|
89
|
+
if ((node = data->frame.node) || (node = data->body))
|
90
|
+
return INT2FIX(nd_line(node));
|
91
|
+
else
|
92
|
+
return Qnil;
|
93
|
+
}
|
94
|
+
|
41
95
|
extern "C" void Init_value_set();
|
42
96
|
extern "C" void Init_swap();
|
43
97
|
|
@@ -45,6 +99,9 @@ extern "C" void Init_faster()
|
|
45
99
|
{
|
46
100
|
rb_define_method(rb_mEnumerable, "each_uniq", RUBY_METHOD_FUNC(enumerable_each_uniq), 0);
|
47
101
|
rb_define_method(rb_mKernel, "is_singleton?", RUBY_METHOD_FUNC(kernel_is_singleton_p), 0);
|
102
|
+
rb_define_method(rb_cProc, "same_body?", RUBY_METHOD_FUNC(proc_same_body_p), 1);
|
103
|
+
rb_define_method(rb_cProc, "file", RUBY_METHOD_FUNC(proc_file), 0);
|
104
|
+
rb_define_method(rb_cProc, "line", RUBY_METHOD_FUNC(proc_line), 0);
|
48
105
|
|
49
106
|
Init_value_set();
|
50
107
|
Init_swap();
|
@@ -0,0 +1,72 @@
|
|
1
|
+
#ifndef __RUBY_INTERNALS_HH__
|
2
|
+
#define __RUBY_INTERNALS_HH__
|
3
|
+
|
4
|
+
/* WARNING: this file contains copies of internal Ruby structures. They are not supposed to be copied (I think ;-)), but I had to nonetheless.
|
5
|
+
* The following methods depend on these:
|
6
|
+
*
|
7
|
+
* Kernel.swap!
|
8
|
+
* Proc#same_body?
|
9
|
+
* Proc#file
|
10
|
+
* Proc#line
|
11
|
+
*/
|
12
|
+
|
13
|
+
#include <ruby.h>
|
14
|
+
#include <intern.h>
|
15
|
+
#include <node.h>
|
16
|
+
#include <re.h>
|
17
|
+
#include <env.h>
|
18
|
+
|
19
|
+
typedef struct RVALUE {
|
20
|
+
union {
|
21
|
+
struct {
|
22
|
+
unsigned long flags; /* always 0 for freed obj */
|
23
|
+
struct RVALUE *next;
|
24
|
+
} free;
|
25
|
+
struct RBasic basic;
|
26
|
+
struct RObject object;
|
27
|
+
struct RClass klass;
|
28
|
+
struct RFloat flonum;
|
29
|
+
struct RString string;
|
30
|
+
struct RArray array;
|
31
|
+
struct RRegexp regexp;
|
32
|
+
struct RHash hash;
|
33
|
+
struct RData data;
|
34
|
+
struct RStruct rstruct;
|
35
|
+
struct RBignum bignum;
|
36
|
+
struct RFile file;
|
37
|
+
struct RNode node;
|
38
|
+
struct RMatch match;
|
39
|
+
struct RVarmap varmap;
|
40
|
+
struct SCOPE scope;
|
41
|
+
} as;
|
42
|
+
#ifdef GC_DEBUG
|
43
|
+
char *file;
|
44
|
+
int line;
|
45
|
+
#endif
|
46
|
+
} RVALUE;
|
47
|
+
static const size_t SLOT_SIZE = sizeof(RVALUE);
|
48
|
+
|
49
|
+
/* This is a copy of Ruby 1.8.5 BLOCK structure. It sucks to copy it here,
|
50
|
+
* but it is not public in Ruby and it is needed to define same_body? */
|
51
|
+
struct BLOCK {
|
52
|
+
NODE *var;
|
53
|
+
NODE *body;
|
54
|
+
VALUE self;
|
55
|
+
struct FRAME frame;
|
56
|
+
struct SCOPE *scope;
|
57
|
+
VALUE klass;
|
58
|
+
NODE *cref;
|
59
|
+
int iter;
|
60
|
+
int vmode;
|
61
|
+
int flags;
|
62
|
+
int uniq;
|
63
|
+
struct RVarmap *dyna_vars;
|
64
|
+
VALUE orig_thread;
|
65
|
+
VALUE wrapper;
|
66
|
+
VALUE block_obj;
|
67
|
+
struct BLOCK *outer;
|
68
|
+
struct BLOCK *prev;
|
69
|
+
};
|
70
|
+
|
71
|
+
#endif
|
72
|
+
|
data/ext/swap.cc
CHANGED
@@ -1,38 +1,4 @@
|
|
1
|
-
#include
|
2
|
-
#include <intern.h>
|
3
|
-
#include <node.h>
|
4
|
-
#include <re.h>
|
5
|
-
#include <env.h>
|
6
|
-
|
7
|
-
typedef struct RVALUE {
|
8
|
-
union {
|
9
|
-
struct {
|
10
|
-
unsigned long flags; /* always 0 for freed obj */
|
11
|
-
struct RVALUE *next;
|
12
|
-
} free;
|
13
|
-
struct RBasic basic;
|
14
|
-
struct RObject object;
|
15
|
-
struct RClass klass;
|
16
|
-
struct RFloat flonum;
|
17
|
-
struct RString string;
|
18
|
-
struct RArray array;
|
19
|
-
struct RRegexp regexp;
|
20
|
-
struct RHash hash;
|
21
|
-
struct RData data;
|
22
|
-
struct RStruct rstruct;
|
23
|
-
struct RBignum bignum;
|
24
|
-
struct RFile file;
|
25
|
-
struct RNode node;
|
26
|
-
struct RMatch match;
|
27
|
-
struct RVarmap varmap;
|
28
|
-
struct SCOPE scope;
|
29
|
-
} as;
|
30
|
-
#ifdef GC_DEBUG
|
31
|
-
char *file;
|
32
|
-
int line;
|
33
|
-
#endif
|
34
|
-
} RVALUE;
|
35
|
-
static const size_t SLOT_SIZE = sizeof(RVALUE);
|
1
|
+
#include "ruby_internals.h"
|
36
2
|
|
37
3
|
/*
|
38
4
|
* Kernel.swap!(obj1, obj2, *args)
|
data/ext/value_set.cc
CHANGED
@@ -9,7 +9,6 @@ using namespace std;
|
|
9
9
|
|
10
10
|
static VALUE cValueSet;
|
11
11
|
static ID id_new;
|
12
|
-
static ID id_to_value_set;
|
13
12
|
|
14
13
|
typedef std::set<VALUE> ValueSet;
|
15
14
|
static ValueSet& get_wrapped_set(VALUE self)
|
@@ -110,7 +109,9 @@ static VALUE value_set_to_value_set(VALUE self) { return self; }
|
|
110
109
|
static VALUE value_set_include_all_p(VALUE vself, VALUE vother)
|
111
110
|
{
|
112
111
|
ValueSet const& self = get_wrapped_set(vself);
|
113
|
-
|
112
|
+
if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
|
113
|
+
rb_raise(rb_eArgError, "expected a ValueSet");
|
114
|
+
ValueSet const& other = get_wrapped_set(vother);
|
114
115
|
return std::includes(self.begin(), self.end(), other.begin(), other.end()) ? Qtrue : Qfalse;
|
115
116
|
}
|
116
117
|
|
@@ -124,7 +125,9 @@ static VALUE value_set_include_all_p(VALUE vself, VALUE vother)
|
|
124
125
|
static VALUE value_set_union(VALUE vself, VALUE vother)
|
125
126
|
{
|
126
127
|
ValueSet const& self = get_wrapped_set(vself);
|
127
|
-
|
128
|
+
if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
|
129
|
+
rb_raise(rb_eArgError, "expected a ValueSet");
|
130
|
+
ValueSet const& other = get_wrapped_set(vother);
|
128
131
|
|
129
132
|
VALUE vresult = rb_funcall(cValueSet, id_new, 0);
|
130
133
|
ValueSet& result = get_wrapped_set(vresult);
|
@@ -141,7 +144,9 @@ static VALUE value_set_union(VALUE vself, VALUE vother)
|
|
141
144
|
static VALUE value_set_merge(VALUE vself, VALUE vother)
|
142
145
|
{
|
143
146
|
ValueSet& self = get_wrapped_set(vself);
|
144
|
-
|
147
|
+
if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
|
148
|
+
rb_raise(rb_eArgError, "expected a ValueSet");
|
149
|
+
ValueSet const& other = get_wrapped_set(vother);
|
145
150
|
|
146
151
|
self.insert(other.begin(), other.end());
|
147
152
|
return vself;
|
@@ -157,7 +162,9 @@ static VALUE value_set_merge(VALUE vself, VALUE vother)
|
|
157
162
|
static VALUE value_set_intersection(VALUE vself, VALUE vother)
|
158
163
|
{
|
159
164
|
ValueSet const& self = get_wrapped_set(vself);
|
160
|
-
|
165
|
+
if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
|
166
|
+
rb_raise(rb_eArgError, "expected a ValueSet");
|
167
|
+
ValueSet const& other = get_wrapped_set(vother);
|
161
168
|
|
162
169
|
VALUE vresult = rb_funcall(cValueSet, id_new, 0);
|
163
170
|
ValueSet& result = get_wrapped_set(vresult);
|
@@ -165,6 +172,37 @@ static VALUE value_set_intersection(VALUE vself, VALUE vother)
|
|
165
172
|
std::inserter(result, result.end()));
|
166
173
|
return vresult;
|
167
174
|
}
|
175
|
+
|
176
|
+
/* call-seq:
|
177
|
+
* set.intersects?(other) => true or false
|
178
|
+
*
|
179
|
+
* Returns true if there is elements in +set+ that are also in +other
|
180
|
+
*/
|
181
|
+
static VALUE value_set_intersects(VALUE vself, VALUE vother)
|
182
|
+
{
|
183
|
+
ValueSet const& self = get_wrapped_set(vself);
|
184
|
+
if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
|
185
|
+
rb_raise(rb_eArgError, "expected a ValueSet");
|
186
|
+
ValueSet const& other = get_wrapped_set(vother);
|
187
|
+
|
188
|
+
ValueSet::const_iterator
|
189
|
+
self_it = self.begin(),
|
190
|
+
self_end = self.end(),
|
191
|
+
other_it = other.begin(),
|
192
|
+
other_end = other.end();
|
193
|
+
|
194
|
+
while(self_it != self_end && other_it != other_end)
|
195
|
+
{
|
196
|
+
if (*self_it < *other_it)
|
197
|
+
++self_it;
|
198
|
+
else if (*other_it < *self_it)
|
199
|
+
++other_it;
|
200
|
+
else
|
201
|
+
return Qtrue;
|
202
|
+
}
|
203
|
+
return Qfalse;
|
204
|
+
}
|
205
|
+
|
168
206
|
/* call-seq:
|
169
207
|
* set.difference(other) => difference_set
|
170
208
|
* set - other => difference_set
|
@@ -175,7 +213,9 @@ static VALUE value_set_intersection(VALUE vself, VALUE vother)
|
|
175
213
|
static VALUE value_set_difference(VALUE vself, VALUE vother)
|
176
214
|
{
|
177
215
|
ValueSet const& self = get_wrapped_set(vself);
|
178
|
-
|
216
|
+
if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
|
217
|
+
rb_raise(rb_eArgError, "expected a ValueSet");
|
218
|
+
ValueSet const& other = get_wrapped_set(vother);
|
179
219
|
|
180
220
|
VALUE vresult = rb_funcall(cValueSet, id_new, 0);
|
181
221
|
ValueSet& result = get_wrapped_set(vresult);
|
@@ -219,10 +259,9 @@ static VALUE value_set_delete(VALUE vself, VALUE v)
|
|
219
259
|
static VALUE value_set_equal(VALUE vself, VALUE vother)
|
220
260
|
{
|
221
261
|
ValueSet const& self = get_wrapped_set(vself);
|
222
|
-
if (!
|
262
|
+
if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
|
223
263
|
return Qfalse;
|
224
|
-
|
225
|
-
ValueSet const& other = get_wrapped_set(rb_funcall(vother, id_to_value_set, 0));
|
264
|
+
ValueSet const& other = get_wrapped_set(vother);
|
226
265
|
return (self == other) ? Qtrue : Qfalse;
|
227
266
|
}
|
228
267
|
|
@@ -244,7 +283,7 @@ static VALUE value_set_clear(VALUE self)
|
|
244
283
|
*/
|
245
284
|
static VALUE value_set_initialize_copy(VALUE vself, VALUE vother)
|
246
285
|
{
|
247
|
-
ValueSet const& other = get_wrapped_set(
|
286
|
+
ValueSet const& other = get_wrapped_set(vother);
|
248
287
|
set<VALUE> new_set(other.begin(), other.end());
|
249
288
|
get_wrapped_set(vself).swap(new_set);
|
250
289
|
return vself;
|
@@ -292,13 +331,13 @@ extern "C" void Init_value_set()
|
|
292
331
|
|
293
332
|
cValueSet = rb_define_class("ValueSet", rb_cObject);
|
294
333
|
id_new = rb_intern("new");
|
295
|
-
id_to_value_set = rb_intern("to_value_set");
|
296
334
|
rb_define_alloc_func(cValueSet, value_set_alloc);
|
297
335
|
rb_define_method(cValueSet, "each", RUBY_METHOD_FUNC(value_set_each), 0);
|
298
336
|
rb_define_method(cValueSet, "include?", RUBY_METHOD_FUNC(value_set_include_p), 1);
|
299
337
|
rb_define_method(cValueSet, "include_all?", RUBY_METHOD_FUNC(value_set_include_all_p), 1);
|
300
338
|
rb_define_method(cValueSet, "union", RUBY_METHOD_FUNC(value_set_union), 1);
|
301
339
|
rb_define_method(cValueSet, "intersection", RUBY_METHOD_FUNC(value_set_intersection), 1);
|
340
|
+
rb_define_method(cValueSet, "intersects?", RUBY_METHOD_FUNC(value_set_intersects), 1);
|
302
341
|
rb_define_method(cValueSet, "difference", RUBY_METHOD_FUNC(value_set_difference), 1);
|
303
342
|
rb_define_method(cValueSet, "insert", RUBY_METHOD_FUNC(value_set_insert), 1);
|
304
343
|
rb_define_method(cValueSet, "merge", RUBY_METHOD_FUNC(value_set_merge), 1);
|
data/lib/utilrb/array/to_s.rb
CHANGED
@@ -3,11 +3,11 @@ class Array
|
|
3
3
|
# Unlike #inspect, it calls #to_s on the elements too
|
4
4
|
def to_s
|
5
5
|
stack = (Thread.current[:array_to_s] ||= [])
|
6
|
-
if stack.include?(
|
6
|
+
if stack.include?(object_id)
|
7
7
|
"..."
|
8
8
|
else
|
9
9
|
begin
|
10
|
-
stack.push
|
10
|
+
stack.push object_id
|
11
11
|
"[" << map { |obj| obj.to_s }.join(", ") << "]"
|
12
12
|
ensure
|
13
13
|
stack.pop
|
data/lib/utilrb/common.rb
CHANGED
@@ -1,8 +1,16 @@
|
|
1
|
-
|
1
|
+
require 'enumerator'
|
2
|
+
|
3
|
+
# An enumerator which iterates on multiple iterators in sequence
|
4
|
+
#
|
5
|
+
# ([1, 2].enum_for + [2, 3].enum_for).each => 1, 2, 2, 3
|
6
|
+
#
|
7
|
+
# See also Enumerator#+
|
2
8
|
class SequenceEnumerator
|
3
9
|
def initialize; @sequence = Array.new end
|
10
|
+
|
11
|
+
def +(other); SequenceEnumerator.new << self << other end
|
4
12
|
# Adds +object+ at the back of the sequence
|
5
|
-
def <<(
|
13
|
+
def <<(other); @sequence << other; self end
|
6
14
|
|
7
15
|
def each
|
8
16
|
@sequence.each { |enum| enum.each { |o| yield(o) } } if block_given?
|
@@ -12,7 +20,7 @@ class SequenceEnumerator
|
|
12
20
|
include Enumerable
|
13
21
|
end
|
14
22
|
|
15
|
-
|
23
|
+
class Enumerable::Enumerator # :nodoc
|
16
24
|
# Builds a sequence of enumeration object.
|
17
25
|
# ([1, 2].enum_for + [2, 3]).each => 1, 2, 2, 3
|
18
26
|
def +(other_enumerator) # :nodoc
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'utilrb/kernel/options'
|
1
2
|
|
2
3
|
class Exception
|
3
4
|
# Returns the full exception message, with backtrace, like the one we get from
|
@@ -16,9 +17,40 @@ class Exception
|
|
16
17
|
# test.rb:3:in `test': this is a test (RuntimeError)
|
17
18
|
# from test.rb:7
|
18
19
|
#
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
# Two regular expressions can be given through the +options+ hash to filter the backtrace:
|
21
|
+
# since::
|
22
|
+
# Only the methods *below* the first matching line will be displayed. The matching
|
23
|
+
# line is included.
|
24
|
+
# until::
|
25
|
+
# Only the methods *above* the first matching line will be displayed. The matching
|
26
|
+
# line is *not* included
|
27
|
+
#
|
28
|
+
# If a block is given, each line of the backtrace are yield and only the lines for which
|
29
|
+
# the block returns true are displayed
|
30
|
+
#
|
31
|
+
def full_message(options = {}, &block)
|
32
|
+
options = validate_options options, [:since, :until]
|
33
|
+
since_matches, until_matches = options[:since], options[:until]
|
34
|
+
|
35
|
+
trace = backtrace
|
36
|
+
if since_matches || until_matches
|
37
|
+
found_beginning, found_end = !since_matches, false
|
38
|
+
trace = trace.find_all do |line|
|
39
|
+
found_beginning ||= (line =~ since_matches)
|
40
|
+
found_end ||= (line =~ until_matches) if until_matches
|
41
|
+
found_beginning && !found_end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
first, *remaining = if block_given? then trace.find_all(&block)
|
46
|
+
else trace
|
47
|
+
end
|
48
|
+
|
49
|
+
msg = "#{first}: #{message} (#{self.class})"
|
50
|
+
unless remaining.empty?
|
51
|
+
msg << "\n\tfrom " + remaining.join("\n\tfrom ")
|
52
|
+
end
|
53
|
+
msg
|
22
54
|
end
|
23
55
|
end
|
24
56
|
|
@@ -1,6 +1,25 @@
|
|
1
|
+
require 'utilrb/common'
|
1
2
|
class Module
|
2
|
-
|
3
|
-
|
3
|
+
Utilrb.if_faster do
|
4
|
+
# Check if +klass+ is an ancestor of this class/module
|
5
|
+
#
|
6
|
+
# It works for singleton classes as well:
|
7
|
+
#
|
8
|
+
# class MyClass; end
|
9
|
+
# obj = MyClass.new
|
10
|
+
# singleton = class << obj; obj end
|
11
|
+
#
|
12
|
+
# singleton.has_ancestor?(MyClass) # => true
|
13
|
+
#
|
14
|
+
def has_ancestor?(klass)
|
15
|
+
self == klass || self < klass || (is_singleton? && superclass.has_ancestor?(klass))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
Utilrb.unless_faster do
|
19
|
+
def has_ancestor?(klass) # :nodoc:
|
20
|
+
self == klass || self < klass || superclass == klass || superclass < klass
|
21
|
+
end
|
22
|
+
end
|
4
23
|
end
|
5
24
|
|
6
25
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Module
|
2
|
+
# Defines a +name+ predicate (name should end with '?'), and if writable is true
|
3
|
+
# a writer method which is +name+ without '?'
|
4
|
+
#
|
5
|
+
# The predicate reads the instance variable which is +name+ without the '?'
|
6
|
+
def attr_predicate(name, writable = false)
|
7
|
+
attr_name = name.to_s.gsub(/\?$/, '')
|
8
|
+
attr_reader attr_name
|
9
|
+
alias_method "#{attr_name}?", attr_name
|
10
|
+
remove_method attr_name
|
11
|
+
|
12
|
+
if writable
|
13
|
+
class_eval "def #{attr_name}=(value); @#{attr_name} = !!value end"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Utilrb
|
2
|
+
# Access to information from pkg-config(1)
|
3
|
+
class PkgConfig
|
4
|
+
class NotFound < RuntimeError
|
5
|
+
attr_reader :name
|
6
|
+
def initialize(name); @name = name end
|
7
|
+
def to_s; "#{name} is not available to pkg-config" end
|
8
|
+
end
|
9
|
+
|
10
|
+
# The module name
|
11
|
+
attr_reader :name
|
12
|
+
# The module version
|
13
|
+
attr_reader :version
|
14
|
+
|
15
|
+
# Create a PkgConfig object for the package +name+
|
16
|
+
# Raises PkgConfig::NotFound if the module does not exist
|
17
|
+
def initialize(name)
|
18
|
+
if !system("pkg-config --exists #{name}")
|
19
|
+
raise NotFound.new(name)
|
20
|
+
end
|
21
|
+
|
22
|
+
@name = name
|
23
|
+
@version = `pkg-config --modversion #{name}`.chomp.strip
|
24
|
+
@actions = Hash.new
|
25
|
+
@variables = Hash.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.define_action(action)
|
29
|
+
define_method(action.gsub(/-/, '_')) do
|
30
|
+
@actions[action] ||= `pkg-config --#{action} #{name}`.chomp.strip
|
31
|
+
end
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
|
35
|
+
ACTIONS = %w{cflags cflags-only-I cflags-only-other
|
36
|
+
libs libs-only-L libs-only-l libs-only-other static}
|
37
|
+
ACTIONS.each { |action| define_action(action) }
|
38
|
+
|
39
|
+
def method_missing(varname, *args, &proc)
|
40
|
+
if args.empty?
|
41
|
+
@variables[varname] ||= `pkg-config --variable=#{varname} #{name}`.chomp.strip
|
42
|
+
else
|
43
|
+
super(varname, *args, &proc)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
data/lib/utilrb/time/to_hms.rb
CHANGED
@@ -9,13 +9,13 @@ class Time
|
|
9
9
|
# s, s.ms, m:s, m:s.ms, h:m:s, h:m:s.ms
|
10
10
|
def self.from_hms(string)
|
11
11
|
unless string =~ /(?:^|:)(\d+)(?:$|\.)/
|
12
|
-
raise "
|
12
|
+
raise ArgumentError, "#{string} found, expected [[h:]m:]s[.ms]"
|
13
13
|
end
|
14
14
|
hm, ms = $`, $'
|
15
15
|
|
16
16
|
s = Integer($1)
|
17
17
|
unless hm =~ /^(?:(\d*):)?(?:(\d*))?$/
|
18
|
-
raise "
|
18
|
+
raise ArgumentError, "found #{hm}, expected nothing, m: or h:m:"
|
19
19
|
end
|
20
20
|
h, m = if $2.empty? then
|
21
21
|
if $1 then [0, Integer($1)]
|
@@ -27,7 +27,7 @@ class Time
|
|
27
27
|
ms = if ms.empty? then 0
|
28
28
|
else
|
29
29
|
unless ms =~ /^\d*$/
|
30
|
-
raise "
|
30
|
+
raise ArgumentError, "found #{string}, expected a number"
|
31
31
|
end
|
32
32
|
ms += "0" * (3 - ms.size)
|
33
33
|
Integer(ms)
|
data/lib/utilrb/value_set.rb
CHANGED
@@ -9,9 +9,25 @@ Utilrb.require_faster("ValueSet") do
|
|
9
9
|
include Enumerable
|
10
10
|
|
11
11
|
def to_s
|
12
|
-
|
13
|
-
|
12
|
+
stack = (Thread.current[:__value_set_stack__] ||= ValueSet.new)
|
13
|
+
if stack.include?(self)
|
14
|
+
"..."
|
15
|
+
else
|
16
|
+
stack << self
|
17
|
+
|
18
|
+
base = super[0..-2]
|
19
|
+
"#{base} { #{to_a.map { |o| o.to_s }.join(", ")} }"
|
20
|
+
end
|
21
|
+
ensure
|
22
|
+
stack.delete(self)
|
14
23
|
end
|
15
24
|
alias :inspect :to_s
|
25
|
+
|
26
|
+
def _dump(lvl = -1)
|
27
|
+
Marshal.dump(to_a)
|
28
|
+
end
|
29
|
+
def self._load(str)
|
30
|
+
Marshal.load(str).to_value_set
|
31
|
+
end
|
16
32
|
end
|
17
33
|
end
|
data/test/test_enumerable.rb
CHANGED
@@ -43,6 +43,7 @@ class TC_Enumerable < Test::Unit::TestCase
|
|
43
43
|
c2 = [:d, :e, :f]
|
44
44
|
assert_equal([:a, :b, :c, :d, :e, :f], (c1.to_enum + c2.to_enum).to_a)
|
45
45
|
assert_equal([:a, :b, :c, :d, :e, :f], [c1, c2].inject(null_enum) { |a, b| a + b }.to_a)
|
46
|
+
assert_equal([:a, :b, :c, :d, :e, :f], [c1, c2].inject(SequenceEnumerator.new) { |a, b| a << b }.to_a)
|
46
47
|
end
|
47
48
|
|
48
49
|
def test_random_element
|
@@ -66,9 +67,13 @@ class TC_Enumerable < Test::Unit::TestCase
|
|
66
67
|
assert_equal(5, a.size)
|
67
68
|
assert_equal([1, 3, 4, 6, 8], a.to_a)
|
68
69
|
assert(a.include?(1))
|
69
|
-
assert(a.include_all?([4, 1, 8]))
|
70
|
+
assert(a.include_all?([4, 1, 8].to_value_set))
|
70
71
|
assert(!a.include_all?(b))
|
71
72
|
|
73
|
+
assert(a.intersects?(b))
|
74
|
+
assert(b.intersects?(a))
|
75
|
+
assert(!a.intersects?([2, 9, 12].to_value_set))
|
76
|
+
|
72
77
|
assert(a.object_id == a.to_value_set.object_id)
|
73
78
|
|
74
79
|
assert_equal([1, 2, 3, 4, 6, 8, 11], (a.union(b)).to_a)
|
@@ -87,6 +92,12 @@ class TC_Enumerable < Test::Unit::TestCase
|
|
87
92
|
|
88
93
|
assert_equal([1,3,5].to_value_set, [1, 2, 3, 4, 5, 6].to_value_set.delete_if { |v| v % 2 == 0 })
|
89
94
|
end
|
95
|
+
|
96
|
+
def test_value_set_recursive_to_s
|
97
|
+
v = [1, 2].to_value_set
|
98
|
+
v << v
|
99
|
+
assert_nothing_raised { v.to_s }
|
100
|
+
end
|
90
101
|
end
|
91
102
|
end
|
92
103
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'test_config'
|
2
|
+
require 'utilrb/exception'
|
3
|
+
require 'flexmock'
|
4
|
+
|
5
|
+
class TC_Exception < Test::Unit::TestCase
|
6
|
+
def test_full_message
|
7
|
+
FlexMock.use do |mock|
|
8
|
+
error = Exception.new
|
9
|
+
def error.message; "this is an error" end
|
10
|
+
def error.backtrace
|
11
|
+
(0..10).map { |i| i.to_s }
|
12
|
+
end
|
13
|
+
|
14
|
+
full = error.full_message.split("\n")
|
15
|
+
assert_equal(11, full.size)
|
16
|
+
|
17
|
+
filtered = error.full_message { |line| Integer(line) % 2 == 0 }.split("\n")
|
18
|
+
assert_equal(6, filtered.size)
|
19
|
+
assert_equal(full.values_at(0, 2, 4, 6, 8, 10), filtered)
|
20
|
+
|
21
|
+
since_matches = error.full_message(:since => /4/).split("\n")
|
22
|
+
assert_equal(7, since_matches.size)
|
23
|
+
assert_equal(full.values_at(*(5..10)), since_matches[1..-1])
|
24
|
+
|
25
|
+
until_matches = error.full_message(:until => /3/).split("\n")
|
26
|
+
assert_equal(3, until_matches.size)
|
27
|
+
assert_equal(full.values_at(1, 2), until_matches[1..-1])
|
28
|
+
|
29
|
+
since_and_until = error.full_message(:since => /3/, :until => /6/).split("\n")
|
30
|
+
assert_equal(3, since_and_until.size)
|
31
|
+
assert_equal(full.values_at(4, 5), since_and_until[1..-1])
|
32
|
+
|
33
|
+
all = error.full_message(:since => /3/, :until => /6/) { |line| Integer(line) % 2 == 0 }.split("\n")
|
34
|
+
assert_equal(1, all.size)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
data/test/test_module.rb
CHANGED
@@ -123,5 +123,25 @@ class TC_Module < Test::Unit::TestCase
|
|
123
123
|
assert_equal([[:base, 10], [:overriden, 20], [:overriden, 15], [:derived, 25]].to_set, derived.enum_for(:each_mapped, nil, false).to_set)
|
124
124
|
assert_equal([[:base, 10], [:overriden, 15], [:derived, 25]].to_set, derived.enum_for(:each_mapped, nil, true).to_set)
|
125
125
|
end
|
126
|
+
|
127
|
+
def test_has_ancestor
|
128
|
+
mod = Module.new
|
129
|
+
parent = Class.new do
|
130
|
+
include mod
|
131
|
+
end
|
132
|
+
child = Class.new(parent)
|
133
|
+
singleton = child.new.singleton_class
|
134
|
+
|
135
|
+
assert(child.has_ancestor?(parent))
|
136
|
+
assert(child.has_ancestor?(mod))
|
137
|
+
assert(parent.has_ancestor?(mod))
|
138
|
+
|
139
|
+
assert(singleton.has_ancestor?(parent), singleton.superclass)
|
140
|
+
assert(singleton.has_ancestor?(mod))
|
141
|
+
assert(singleton.has_ancestor?(child))
|
142
|
+
|
143
|
+
assert(!parent.has_ancestor?(child))
|
144
|
+
assert(!parent.has_ancestor?(singleton))
|
145
|
+
end
|
126
146
|
end
|
127
147
|
|
data/test/test_object.rb
CHANGED
@@ -61,5 +61,24 @@ class TC_Object < Test::Unit::TestCase
|
|
61
61
|
assert_equal(klass, object.singleton_class.superclass)
|
62
62
|
assert_equal([object.singleton_class, klass, Object], object.singleton_class.ancestors[0, 3])
|
63
63
|
end
|
64
|
+
|
65
|
+
def test_attr_predicate
|
66
|
+
klass = Class.new do
|
67
|
+
attr_predicate :working
|
68
|
+
attr_predicate :not_working, true
|
69
|
+
end
|
70
|
+
assert(klass.method_defined?(:working?))
|
71
|
+
assert(!klass.method_defined?(:working))
|
72
|
+
assert(!klass.method_defined?(:working=))
|
73
|
+
assert(klass.method_defined?(:not_working?))
|
74
|
+
assert(!klass.method_defined?(:not_working))
|
75
|
+
assert(klass.method_defined?(:not_working=))
|
76
|
+
|
77
|
+
object = klass.new
|
78
|
+
object.instance_eval { @working = true }
|
79
|
+
assert(object.working?)
|
80
|
+
object.not_working = 5
|
81
|
+
assert_equal(true, object.not_working?)
|
82
|
+
end
|
64
83
|
end
|
65
84
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'set'
|
3
|
+
require 'utilrb/pkgconfig'
|
4
|
+
|
5
|
+
class TC_PkgConfig < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@old_pkg_config_path = ENV['PKG_CONFIG_PATH']
|
8
|
+
ENV['PKG_CONFIG_PATH'] = File.join(File.expand_path(File.dirname(__FILE__)), 'data')
|
9
|
+
end
|
10
|
+
def teardown
|
11
|
+
ENV['PKG_CONFIG_PATH'] = @old_pkg_config_path
|
12
|
+
end
|
13
|
+
|
14
|
+
PkgConfig = Utilrb::PkgConfig
|
15
|
+
def test_find_package
|
16
|
+
STDERR.puts ENV['PKG_CONFIG_PATH']
|
17
|
+
assert_raises(PkgConfig::NotFound) { PkgConfig.new('does_not_exist') }
|
18
|
+
assert_nothing_raised { PkgConfig.new('test_pkgconfig') }
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_load
|
22
|
+
pkg = PkgConfig.new('test_pkgconfig')
|
23
|
+
assert_equal('test_pkgconfig', pkg.name)
|
24
|
+
assert_equal('4.2', pkg.version)
|
25
|
+
|
26
|
+
assert_equal('a_prefix', pkg.prefix)
|
27
|
+
assert_equal(%w{-Ia_prefix/include -O3}.to_set, pkg.cflags.split.to_set)
|
28
|
+
assert_equal('-Ia_prefix/include', pkg.cflags_only_I)
|
29
|
+
assert_equal('-O3', pkg.cflags_only_other)
|
30
|
+
|
31
|
+
assert_equal(%w{-ltest -lother -La_prefix/lib}.to_set, pkg.libs.split.to_set)
|
32
|
+
assert_equal('-La_prefix/lib', pkg.libs_only_L)
|
33
|
+
assert_equal(%w{-ltest -lother}.to_set, pkg.libs_only_l.split.to_set)
|
34
|
+
end
|
35
|
+
end
|
data/test/test_proc.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'utilrb'
|
3
|
+
|
4
|
+
Utilrb.require_faster('TC_Proc') do
|
5
|
+
class TC_Proc < Test::Unit::TestCase
|
6
|
+
def block_to_proc_helper(&block); block end
|
7
|
+
def block_to_proc
|
8
|
+
[block_to_proc_helper { blo }, block_to_proc_helper { bla }]
|
9
|
+
end
|
10
|
+
def test_same_body
|
11
|
+
a1, a2 = block_to_proc
|
12
|
+
b1, b2 = block_to_proc
|
13
|
+
assert(a1.same_body?(b1))
|
14
|
+
assert(a2.same_body?(b2))
|
15
|
+
assert(!a1.same_body?(b2))
|
16
|
+
assert(!a2.same_body?(b1))
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_line
|
20
|
+
assert_equal(8, block_to_proc.first.line)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_file
|
24
|
+
assert_equal(File.expand_path(__FILE__), File.expand_path(block_to_proc.first.file))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.
|
2
|
+
rubygems_version: 0.9.2
|
3
3
|
specification_version: 1
|
4
4
|
name: utilrb
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0
|
7
|
-
date: 2007-
|
6
|
+
version: "1.0"
|
7
|
+
date: 2007-03-31 00:00:00 +02:00
|
8
8
|
summary: Yet another Ruby toolkit
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -39,6 +39,7 @@ files:
|
|
39
39
|
- bm/speed.rb
|
40
40
|
- ext/extconf.rb
|
41
41
|
- ext/faster.cc
|
42
|
+
- ext/ruby_internals.h
|
42
43
|
- ext/swap.cc
|
43
44
|
- ext/value_set.cc
|
44
45
|
- lib/utilrb.rb
|
@@ -70,6 +71,7 @@ files:
|
|
70
71
|
- lib/utilrb/module.rb
|
71
72
|
- lib/utilrb/module/ancestor_p.rb
|
72
73
|
- lib/utilrb/module/attr_enumerable.rb
|
74
|
+
- lib/utilrb/module/attr_predicate.rb
|
73
75
|
- lib/utilrb/module/define_method.rb
|
74
76
|
- lib/utilrb/module/include.rb
|
75
77
|
- lib/utilrb/module/inherited_enumerable.rb
|
@@ -78,8 +80,7 @@ files:
|
|
78
80
|
- lib/utilrb/object/attribute.rb
|
79
81
|
- lib/utilrb/object/singleton_class.rb
|
80
82
|
- lib/utilrb/objectstats.rb
|
81
|
-
- lib/utilrb/
|
82
|
-
- lib/utilrb/queue/get.rb
|
83
|
+
- lib/utilrb/pkgconfig.rb
|
83
84
|
- lib/utilrb/set.rb
|
84
85
|
- lib/utilrb/set/to_s.rb
|
85
86
|
- lib/utilrb/time.rb
|
@@ -87,10 +88,11 @@ files:
|
|
87
88
|
- lib/utilrb/unbound_method.rb
|
88
89
|
- lib/utilrb/unbound_method/call.rb
|
89
90
|
- lib/utilrb/value_set.rb
|
90
|
-
-
|
91
|
+
- test/data/test_pkgconfig.pc
|
91
92
|
- test/test_array.rb
|
92
93
|
- test/test_config.rb
|
93
94
|
- test/test_enumerable.rb
|
95
|
+
- test/test_exception.rb
|
94
96
|
- test/test_gc.rb
|
95
97
|
- test/test_hash.rb
|
96
98
|
- test/test_kernel.rb
|
@@ -98,9 +100,13 @@ files:
|
|
98
100
|
- test/test_module.rb
|
99
101
|
- test/test_object.rb
|
100
102
|
- test/test_objectstats.rb
|
103
|
+
- test/test_pkgconfig.rb
|
104
|
+
- test/test_proc.rb
|
101
105
|
- test/test_time.rb
|
102
106
|
- test/test_unbound_method.rb
|
103
107
|
test_files:
|
108
|
+
- test/test_proc.rb
|
109
|
+
- test/test_exception.rb
|
104
110
|
- test/test_time.rb
|
105
111
|
- test/test_misc.rb
|
106
112
|
- test/test_module.rb
|
@@ -113,6 +119,7 @@ test_files:
|
|
113
119
|
- test/test_enumerable.rb
|
114
120
|
- test/test_hash.rb
|
115
121
|
- test/test_objectstats.rb
|
122
|
+
- test/test_pkgconfig.rb
|
116
123
|
rdoc_options: []
|
117
124
|
|
118
125
|
extra_rdoc_files: []
|
@@ -140,5 +147,5 @@ dependencies:
|
|
140
147
|
requirements:
|
141
148
|
- - ">="
|
142
149
|
- !ruby/object:Gem::Version
|
143
|
-
version: 1.
|
150
|
+
version: 1.2.0
|
144
151
|
version:
|
data/lib/utilrb/queue/get.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
class Queue
|
2
|
-
# Returns all elements currently in the queue. If +non_block+ is true,
|
3
|
-
# returns an empty array if the queue is empty
|
4
|
-
#
|
5
|
-
# WARNING: this method is NOT compatible with fastthread's Queue implementation
|
6
|
-
# If you rely on Queue#get and want to use fastthread, you will have to patch
|
7
|
-
# fastthread with patches/fastthread-queue-get.patch
|
8
|
-
unless instance_methods.include?("get")
|
9
|
-
def get(non_block = false)
|
10
|
-
while (Thread.critical = true; @que.empty?)
|
11
|
-
return [] if non_block
|
12
|
-
@waiting.push Thread.current
|
13
|
-
Thread.stop
|
14
|
-
end
|
15
|
-
result = @que.dup
|
16
|
-
@que.clear
|
17
|
-
result
|
18
|
-
ensure
|
19
|
-
Thread.critical = false
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/lib/utilrb/queue.rb
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
--- fastthread-0.6.2/ext/fastthread/fastthread.c 2007-01-25 12:09:54.956708000 +0100
|
2
|
-
+++ fastthread-0.6.2.new/ext/fastthread/fastthread.c 2007-01-25 11:49:49.151455000 +0100
|
3
|
-
@@ -737,6 +737,61 @@ rb_queue_marshal_load(self, data)
|
4
|
-
|
5
|
-
static VALUE rb_queue_marshal_dump _((VALUE));
|
6
|
-
|
7
|
-
+
|
8
|
-
+/* call-seq:
|
9
|
-
+ * Queue#get(non_block = false) => array
|
10
|
-
+ *
|
11
|
-
+ * Returns an array containing all elements currently in the queue. After a call
|
12
|
-
+ * to #get, the queue is empty. If non_block is false, the call will block until
|
13
|
-
+ * there is something in it. Otherwise, if the queue is empty, it returns an empty
|
14
|
-
+ * array.
|
15
|
-
+ */
|
16
|
-
+static VALUE
|
17
|
-
+rb_queue_get(argc, argv, self)
|
18
|
-
+ int argc;
|
19
|
-
+ VALUE *argv;
|
20
|
-
+ VALUE self;
|
21
|
-
+{
|
22
|
-
+ Queue *queue;
|
23
|
-
+ int should_block;
|
24
|
-
+ VALUE result;
|
25
|
-
+ Data_Get_Struct(self, Queue, queue);
|
26
|
-
+
|
27
|
-
+ if ( argc == 0 ) {
|
28
|
-
+ should_block = 1;
|
29
|
-
+ } else if ( argc == 1 ) {
|
30
|
-
+ should_block = !RTEST(argv[0]);
|
31
|
-
+ } else {
|
32
|
-
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
|
33
|
-
+ }
|
34
|
-
+
|
35
|
-
+ lock_mutex(&queue->mutex);
|
36
|
-
+ if ( !queue->values.entries ) {
|
37
|
-
+ /* NOTE: locking is not needed to check if the queue is empty
|
38
|
-
+ since AFAIK C extensions are never preempted. I do as in #pop
|
39
|
-
+ where it is done.
|
40
|
-
+ */
|
41
|
-
+ if ( !should_block ) {
|
42
|
-
+ unlock_mutex(&queue->mutex);
|
43
|
-
+ return rb_ary_new();
|
44
|
-
+ }
|
45
|
-
+ while (!queue->values.entries) {
|
46
|
-
+ wait_condvar(&queue->value_available, &queue->mutex);
|
47
|
-
+ }
|
48
|
-
+ }
|
49
|
-
+
|
50
|
-
+ result = rb_ary_new();
|
51
|
-
+ while ( queue->values.entries ) {
|
52
|
-
+ rb_ary_push(result, shift_list(&queue->values));
|
53
|
-
+ }
|
54
|
-
+ if ( queue->capacity ) {
|
55
|
-
+ signal_condvar(&queue->space_available);
|
56
|
-
+ }
|
57
|
-
+ unlock_mutex(&queue->mutex);
|
58
|
-
+
|
59
|
-
+ return result;
|
60
|
-
+}
|
61
|
-
+
|
62
|
-
static VALUE
|
63
|
-
rb_queue_marshal_dump(self)
|
64
|
-
VALUE self;
|
65
|
-
@@ -991,6 +1046,7 @@ static VALUE setup_classes(unused)
|
66
|
-
rb_define_method(rb_cQueue, "num_waiting", rb_queue_num_waiting, 0);
|
67
|
-
rb_define_method(rb_cQueue, "pop", rb_queue_pop, -1);
|
68
|
-
rb_define_method(rb_cQueue, "push", rb_queue_push, 1);
|
69
|
-
+ rb_define_method(rb_cQueue, "get", rb_queue_get, -1);
|
70
|
-
rb_alias(rb_cQueue, rb_intern("<<"), rb_intern("push"));
|
71
|
-
rb_alias(rb_cQueue, rb_intern("deq"), rb_intern("pop"));
|
72
|
-
rb_alias(rb_cQueue, rb_intern("shift"), rb_intern("pop"));
|