utilrb 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/Changes.txt +20 -0
  2. data/License.txt +26 -0
  3. data/Manifest.txt +64 -0
  4. data/README.txt +44 -0
  5. data/Rakefile +46 -0
  6. data/bm/allocation.rb +7 -0
  7. data/bm/speed.rb +19 -0
  8. data/ext/extconf.rb +5 -0
  9. data/ext/faster.cc +48 -0
  10. data/ext/swap.cc +61 -0
  11. data/ext/value_set.cc +290 -0
  12. data/lib/utilrb.rb +2 -0
  13. data/lib/utilrb/array.rb +2 -0
  14. data/lib/utilrb/array/to_s.rb +16 -0
  15. data/lib/utilrb/common.rb +50 -0
  16. data/lib/utilrb/enumerable.rb +2 -0
  17. data/lib/utilrb/enumerable/null.rb +18 -0
  18. data/lib/utilrb/enumerable/random_element.rb +16 -0
  19. data/lib/utilrb/enumerable/sequence.rb +24 -0
  20. data/lib/utilrb/enumerable/uniq.rb +61 -0
  21. data/lib/utilrb/exception.rb +2 -0
  22. data/lib/utilrb/exception/full_message.rb +8 -0
  23. data/lib/utilrb/gc.rb +2 -0
  24. data/lib/utilrb/gc/force.rb +11 -0
  25. data/lib/utilrb/hash.rb +2 -0
  26. data/lib/utilrb/hash/slice.rb +6 -0
  27. data/lib/utilrb/hash/to_s.rb +6 -0
  28. data/lib/utilrb/hash/to_sym_keys.rb +6 -0
  29. data/lib/utilrb/kernel.rb +2 -0
  30. data/lib/utilrb/kernel/arity.rb +10 -0
  31. data/lib/utilrb/kernel/options.rb +69 -0
  32. data/lib/utilrb/kernel/poll.rb +24 -0
  33. data/lib/utilrb/kernel/require.rb +12 -0
  34. data/lib/utilrb/kernel/swap.rb +2 -0
  35. data/lib/utilrb/logger.rb +3 -0
  36. data/lib/utilrb/logger/forward.rb +15 -0
  37. data/lib/utilrb/logger/hierarchy.rb +34 -0
  38. data/lib/utilrb/module.rb +2 -0
  39. data/lib/utilrb/module/ancestor_p.rb +6 -0
  40. data/lib/utilrb/module/attr_enumerable.rb +28 -0
  41. data/lib/utilrb/module/define_method.rb +30 -0
  42. data/lib/utilrb/module/include.rb +30 -0
  43. data/lib/utilrb/module/inherited_enumerable.rb +122 -0
  44. data/lib/utilrb/object.rb +2 -0
  45. data/lib/utilrb/object/address.rb +14 -0
  46. data/lib/utilrb/object/attribute.rb +89 -0
  47. data/lib/utilrb/object/singleton_class.rb +53 -0
  48. data/lib/utilrb/objectstats.rb +52 -0
  49. data/lib/utilrb/time.rb +2 -0
  50. data/lib/utilrb/time/to_hms.rb +6 -0
  51. data/lib/utilrb/unbound_method.rb +2 -0
  52. data/lib/utilrb/unbound_method/call.rb +5 -0
  53. data/lib/utilrb/value_set.rb +17 -0
  54. data/test/test_array.rb +9 -0
  55. data/test/test_config.rb +4 -0
  56. data/test/test_enumerable.rb +89 -0
  57. data/test/test_gc.rb +39 -0
  58. data/test/test_hash.rb +22 -0
  59. data/test/test_kernel.rb +70 -0
  60. data/test/test_misc.rb +42 -0
  61. data/test/test_module.rb +127 -0
  62. data/test/test_object.rb +65 -0
  63. data/test/test_objectstats.rb +19 -0
  64. data/test/test_unbound_method.rb +23 -0
  65. metadata +128 -0
@@ -0,0 +1,2 @@
1
+ require 'utilrb/kernel/require'
2
+ require_dir(__FILE__)
@@ -0,0 +1,6 @@
1
+ class Module
2
+ # Check if +klass+ is an ancestor of this class/module
3
+ def has_ancestor?(klass); ancestors.find { |a| a == klass } end
4
+ end
5
+
6
+
@@ -0,0 +1,28 @@
1
+ require 'utilrb/object/attribute'
2
+
3
+ class Module
4
+ # Define 'name' to be a read-only enumerable attribute. The method
5
+ # defines a +attr_name+ read-only attribute and an enumerator method
6
+ # each_#{name}. +init_block+ is used to initialize the attribute.
7
+ #
8
+ # The enumerator method accepts a +key+ argument. If the attribute is
9
+ # a key => enumerable map, then the +key+ attribute can be used to iterate
10
+ #
11
+ # +enumerator+ is the name of the enumeration method
12
+ def attr_enumerable(name, attr_name = name, enumerator = :each, &init_block)
13
+ class_eval do
14
+ attribute(attr_name, &init_block)
15
+ end
16
+ class_eval <<-EOF
17
+ def each_#{name}(key = nil, &iterator)
18
+ return unless #{attr_name}
19
+ if key
20
+ #{attr_name}[key].#{enumerator}(&iterator)
21
+ else
22
+ #{attr_name}.#{enumerator}(&iterator)
23
+ end
24
+ end
25
+ EOF
26
+ end
27
+ end
28
+
@@ -0,0 +1,30 @@
1
+ class Module
2
+ # Emulate block-passing by converting the block into a Proc object
3
+ # and passing it to the given block as last argument
4
+ # dule)
5
+ #
6
+ # For instance
7
+ # define_method('my_method') do |a, &block|
8
+ # end
9
+ #
10
+ # Is written as
11
+ # define_method_with_block('my_method') do |block, a|
12
+ # end
13
+ #
14
+ # The block is given first to allow the following construct:
15
+ #
16
+ # define_method_with_block('my_method') do |block, *args|
17
+ # end
18
+ #
19
+ # +block+ is +nil+ if no block is given on the method call
20
+ #
21
+ def define_method_with_block(name, &mdef)
22
+ class_eval <<-EOD
23
+ def #{name}(*args, &block)
24
+ dmwb_#{name}_user_definition(block, *args)
25
+ end
26
+ EOD
27
+ define_method("dmwb_#{name}_user_definition", &mdef)
28
+ end
29
+ end
30
+
@@ -0,0 +1,30 @@
1
+ class Module
2
+ unless (method(:__instance_include__) rescue nil)
3
+ alias :__instance_include__ :include
4
+ end
5
+
6
+ # Includes a module in this one, with support for class extensions
7
+ #
8
+ # If a module defines a ClassExtension submodule, then
9
+ # * if it is included in a module, the target's ClassExtension
10
+ # module includes the source ClassExtension (and if there is no
11
+ # ClassExtension in the target, it is created)
12
+ # * if it is included in a Class, the ClassExtension module
13
+ # extends the class.
14
+ def include(mod)
15
+ __instance_include__ mod
16
+ return unless mod.const_defined?(:ClassExtension)
17
+
18
+ if is_a?(Module) && !is_a?(Class)
19
+ unless const_defined?(:ClassExtension)
20
+ const_set(:ClassExtension, Module.new)
21
+ end
22
+ const_get(:ClassExtension).class_eval do
23
+ __instance_include__ mod.const_get(:ClassExtension)
24
+ end
25
+ else
26
+ extend mod.const_get(:ClassExtension)
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,122 @@
1
+ require 'utilrb/object/attribute'
2
+ require 'utilrb/object/singleton_class'
3
+ require 'utilrb/enumerable/uniq'
4
+ require 'utilrb/module/include'
5
+
6
+ class Module
7
+ def define_inherited_enumerable(name, attribute_name = name, options = Hash.new, &init) # :nodoc:
8
+ # Set up the attribute accessor
9
+ attribute(attribute_name, &init)
10
+ class_eval { private "#{attribute_name}=" }
11
+
12
+ options[:enum_with] ||= :each
13
+
14
+ if options[:map]
15
+ class_eval <<-EOF
16
+ def each_#{name}(key = nil, uniq = true)
17
+ if key
18
+ if #{attribute_name}.has_key?(key)
19
+ yield(#{attribute_name}[key])
20
+ return self if uniq
21
+ end
22
+ elsif uniq
23
+ @enum_#{name}_uniq ||= enum_uniq(:each_#{name}, nil, false) { |k, v| k }
24
+ @enum_#{name}_uniq.each { |el| yield(el) }
25
+ return self
26
+ else
27
+ #{attribute_name}.#{options[:enum_with]} { |el| yield(el) }
28
+ end
29
+ if superclass = ancestors[1..-1].find { |k| k.respond_to?(:each_#{name}) }
30
+ superclass.each_#{name}(key, uniq) { |el| yield(el) }
31
+ end
32
+ self
33
+ end
34
+ def has_#{name}?(key)
35
+ return true if #{attribute_name}[key]
36
+ if superclass = ancestors[1..-1].find { |k| k.respond_to?(:has_#{name}) }
37
+ superclass.has_#{name}(key)
38
+ end
39
+ end
40
+ EOF
41
+ else
42
+ class_eval <<-EOF
43
+ def each_#{name}(&iterator)
44
+ #{attribute_name}.#{options[:enum_with]}(&iterator) if #{attribute_name}
45
+ if superclass = ancestors[1..-1].find { |k| k.respond_to?(:each_#{name}) }
46
+ superclass.each_#{name} { |el| yield(el) }
47
+ end
48
+ self
49
+ end
50
+ EOF
51
+ end
52
+ end
53
+
54
+ # Defines an attribute as being enumerable in the class instance and in the
55
+ # whole class inheritance hierarchy. More specifically, it defines a
56
+ # <tt>each_#{name}(&iterator)</tt> instance method and a <tt>each_#{name}(&iterator)</tt>
57
+ # class method which iterates (in order) on
58
+ # - the instance #{name} attribute
59
+ # - the singleton class #{name} attribute
60
+ # - the class #{name} attribute
61
+ # - the superclass #{name} attribute
62
+ # - the superclass' superclass #{name} attribute
63
+ # ...
64
+ #
65
+ # This method can be used on modules, in which case the module is used as if
66
+ # it was part of the inheritance hierarchy.
67
+ #
68
+ # The +name+ option defines the enumeration method name (+value+ will
69
+ # define a +each_value+ method). +attribute_name+ defines the attribute
70
+ # name. +init+ is a block called to initialize the attribute.
71
+ # Valid options in +options+ are:
72
+ # map:: the attribute should respond to +[]+. The enumeration method takes two
73
+ # arguments, +key+ and +uniq+. If +key+ is given, we iterate on the values
74
+ # given by <tt>attribute[key]</tt>. If +uniq+ is true, the enumeration will
75
+ # yield at most one value for each +key+ found (so, if both +key+ and +uniq+ are
76
+ # given, the enumeration yields at most one value)
77
+ #
78
+ # For instance
79
+ #
80
+ # class A
81
+ # class_inherited_enumerable("value", "enum") { Array.new }
82
+ # end
83
+ # module M
84
+ # inherited_enumerable("attr") { Array.new }
85
+ # end
86
+ # class B < A
87
+ # include M
88
+ # end
89
+ # b = B.new
90
+ #
91
+ # A.enum << 1
92
+ # B.enum << 2
93
+ # M.attr << 1
94
+ # class << b
95
+ # enum << 3
96
+ # attr << 4
97
+ # end
98
+ # M.attr << 2
99
+ #
100
+ # A.each_enum => 1
101
+ # B.each_enum => 2, 1
102
+ # b.singleton_class.each_enum => 3, 2, 1
103
+ # b.singleton_class.each_attr => 4, 1, 2
104
+ #
105
+ def inherited_enumerable(name, attribute_name = name, options = Hash.new, &init)
106
+ singleton_class.class_eval { define_inherited_enumerable(name, attribute_name, options, &init) }
107
+
108
+ if is_a?(Module) && !is_a?(Class)
109
+ unless const_defined?(:ClassExtension)
110
+ const_set(:ClassExtension, Module.new)
111
+ end
112
+ class_extension = const_get(:ClassExtension)
113
+ class_extension.class_eval do
114
+ define_inherited_enumerable(name, attribute_name, options, &init)
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+
121
+
122
+
@@ -0,0 +1,2 @@
1
+ require 'utilrb/kernel/require'
2
+ require_dir(__FILE__)
@@ -0,0 +1,14 @@
1
+
2
+ class Object
3
+ # Return the object address (for non immediate
4
+ # objects).
5
+ def address; Object.address_from_id(object_id) end
6
+
7
+ # Converts the object_id of a non-immediate object
8
+ # to its 32 bits address
9
+ def self.address_from_id(id)
10
+ id = 0xFFFFFFFF - ~id if id < 0
11
+ (id * 2) & 0xFFFFFFFF
12
+ end
13
+ end
14
+
@@ -0,0 +1,89 @@
1
+ require 'utilrb/common'
2
+ require 'utilrb/object/singleton_class'
3
+
4
+ Utilrb.unless_faster do
5
+ class Object
6
+ # :call-seq
7
+ # attribute :name => default_value
8
+ # attribute(:name) { default_value }
9
+ #
10
+ # In the first form, defines a read-write attribute
11
+ # named 'name' with default_value for default value.
12
+ # In the second form, the block is called if the attribute
13
+ # is read before it has been ever written, and its return
14
+ # value is used as default value.
15
+ def attribute(attr_def, &init)
16
+ if Hash === attr_def
17
+ name, defval = attr_def.to_a.flatten
18
+ else
19
+ name = attr_def
20
+ end
21
+
22
+ class_eval do
23
+ attr_writer name
24
+ define_method("#{name}_defval") do
25
+ defval || (instance_eval(&init) if init)
26
+ end
27
+ end
28
+
29
+ class_eval <<-EOD
30
+ def #{name}
31
+ if defined? @#{name} then @#{name}
32
+ else @#{name} = #{name}_defval
33
+ end
34
+ end
35
+ EOD
36
+ end
37
+ end
38
+ end
39
+
40
+ Utilrb.if_faster do
41
+ class Object
42
+ # :call-seq
43
+ # attribute :name => default_value
44
+ # attribute(:name) { default_value }
45
+ #
46
+ # In the first form, defines a read-write attribute
47
+ # named 'name' with default_value for default value.
48
+ # In the second form, the block is called if the attribute
49
+ # is read before it has been ever written, and its return
50
+ # value is used as default value.
51
+ def attribute(attr_def, &init)
52
+ if Hash === attr_def
53
+ name, defval = attr_def.to_a.flatten
54
+ else
55
+ name = attr_def
56
+ end
57
+
58
+ if is_singleton? || instance_of?(Module)
59
+ class_eval do
60
+ attr_writer name
61
+ define_method("#{name}_defval") do
62
+ defval || (instance_eval(&init) if init)
63
+ end
64
+ end
65
+
66
+ class_eval <<-EOD
67
+ def #{name}
68
+ if defined? @#{name} then @#{name}
69
+ else @#{name} = #{name}_defval
70
+ end
71
+ end
72
+ EOD
73
+ else
74
+ class_eval { attr_writer name }
75
+ define_method(name) do
76
+ singleton_class.class_eval { attr_reader name }
77
+ instance_variable_set("@#{name}", defval || (instance_eval(&init) if init))
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ class Object
85
+ def class_attribute(attr_def, &init)
86
+ singleton_class.class_eval { attribute(attr_def, &init) }
87
+ end
88
+ end
89
+
@@ -0,0 +1,53 @@
1
+ require 'utilrb/object/address'
2
+ if RUBY_VERSION >= "1.9"
3
+ class Object
4
+ def has_singleton?; defined? @singleton_class end
5
+ def singleton_class
6
+ if defined? @singleton_class
7
+ return @singleton_class
8
+ else
9
+ @singleton_class = class << self
10
+ class << self
11
+ alias __ancestors__ ancestors
12
+ def ancestors; __ancestors__.unshift(self) end
13
+ end
14
+
15
+ self
16
+ end
17
+
18
+ @singleton_class
19
+ end
20
+ end
21
+ end
22
+ else
23
+ class Object
24
+ def has_singleton?
25
+ defined? @singleton_class
26
+ end
27
+ def singleton_class
28
+ if defined? @singleton_class
29
+ return @singleton_class
30
+ else
31
+ klass = class << self; self end
32
+ instance = self
33
+ klass.class_eval do
34
+ @singleton_instance = instance
35
+ @superclass = instance.class
36
+ class << self
37
+ attr_reader :superclass
38
+ attr_reader :singleton_instance
39
+ def name
40
+ "#{@superclass.name}!0x#{@singleton_instance.address.to_s(16)}"
41
+ end
42
+
43
+ alias __ancestors__ ancestors
44
+ def ancestors; __ancestors__.unshift(self) end
45
+ end
46
+ end
47
+
48
+ @singleton_class = klass
49
+ end
50
+ end
51
+ end
52
+ end
53
+
@@ -0,0 +1,52 @@
1
+ require 'utilrb/gc/force'
2
+
3
+ module ObjectStats
4
+ # Allocates no object
5
+ def self.count
6
+ count = 0
7
+ ObjectSpace.each_object { |obj| count += 1}
8
+
9
+ count
10
+ end
11
+
12
+ # Allocates 1 Hash, which is included in the count
13
+ def self.count_by_class
14
+ by_class = Hash.new(0)
15
+ ObjectSpace.each_object { |obj|
16
+ by_class[obj.class] += 1
17
+ by_class
18
+ }
19
+ by_class
20
+ end
21
+
22
+ # Profiles the memory allocation in the block
23
+ # If alive is true, then only non-gcable objects
24
+ # are returned.
25
+ def self.profile(alive = false)
26
+ already_disabled = GC.disable
27
+ before = count_by_class
28
+ yield
29
+ after = count_by_class
30
+ GC.enable unless already_disabled
31
+
32
+ after[Hash] -= 1 # Correction for the call of count_by_class
33
+ profile = before.
34
+ merge(after) { |klass, old, new| new - old }.
35
+ delete_if { |klass, count| count == 0 }
36
+ end
37
+
38
+ def self.stats(filter = nil)
39
+ total_count = 0
40
+ output = ""
41
+ count_by_class.each do |klass, obj_count|
42
+ total_count += obj_count
43
+ if !filter || klass.name =~ filter
44
+ output << klass.name << " " << obj_count.to_s << "\n"
45
+ end
46
+ end
47
+
48
+ (output << "Total object count: #{total_count}")
49
+ end
50
+ end
51
+
52
+
@@ -0,0 +1,2 @@
1
+ require 'utilrb/kernel/require'
2
+ require_dir(__FILE__)