tresse 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/README.md +46 -15
  4. data/lib/tresse.rb +114 -85
  5. data/tresse.gemspec +2 -2
  6. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a1837779d3e8be68176eb4fb52d2cc16d411ce24
4
- data.tar.gz: 504b3c9a5c52290d7fd49bc9ddf24d685c4ea5be
3
+ metadata.gz: 07e2b40e7224b8da9af9768fb077d0a9552b04ba
4
+ data.tar.gz: d5e471d9d944580185fe2aa97e53fec105f87ae8
5
5
  SHA512:
6
- metadata.gz: cb7be058cf592b5ae2e0f75ce973f94acd79c7406fef6301e2b040ce19529d497013b28f95d1e029b38938fbe8c1264fdaf16b234a10d368651ea70a9f1b1a4d
7
- data.tar.gz: 99b7ea37ef5ea2e2dac2e99a3336b137cd282f2aaa619a6d827d42d0f9e341a594022b04278a6be2e2ef8e7ce7ef39fec0487e1f12ea3b9afd48a8d24d88c19c
6
+ metadata.gz: e69445a655dc2d80002b087ff8355d1e344a052919be4944b52c94bef65f4065b3d8eb0cf090a0f0e8276cebc028f002399a8b638d892584b51eaefa2cc881fa
7
+ data.tar.gz: e812e89f78b44ad82726bc978bd36c780957c645b4fc55278279b770f87ed219c5995ea4ed02a16d5196c78b6d0ebeb87e43ba313d847d0789cff2bb2ff63c2b
data/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
  # CHANGELOG.md
3
3
 
4
4
 
5
+ ## tresse 1.0.0 released 2019-09-16
6
+
7
+ * #source / #map / #reduce
8
+ * #each / #flatten
9
+ * work threads
10
+
11
+
5
12
  ## tresse 0.1.0 released 2019-09-15
6
13
 
7
14
  * Initial release
data/README.md CHANGED
@@ -1,41 +1,72 @@
1
1
 
2
2
  # tresse
3
3
 
4
- A poorly thought out and stupid each+map+reduce contraption.
4
+ A poorly thought out and stupid source+map+reduce contraption.
5
5
 
6
+ You source one or more pieces of data, map them a couple of times then reduce them.
7
+
8
+ By default, the whole of Tresse uses 8 work threads, it can be changed:
9
+ ```ruby
10
+ Tresse.max_work_thread_count # => 8
11
+
12
+ Tresse.max_work_thread_count = 10
13
+
14
+ Tresse.max_work_thread_count # => 10
15
+ ```
6
16
 
7
17
  ## use
8
18
 
19
+ Two sources flattened together
20
+ ```ruby
21
+ r =
22
+ Tresse::Group.new('test0')
23
+ .source { (0..3).to_a }
24
+ .source { (4..9).to_a }
25
+ .values # or .flatten
26
+ .sort
27
+
28
+ r #=> (0..9).to_a
9
29
  ```
10
- require 'tresse'
11
30
 
31
+ Combining two sources again
32
+ ```ruby
12
33
  r =
13
34
  Tresse::Group.new('test0')
14
- .append { 'b' }
15
- .append { 'a' }
16
- .collect { |e| e * 2 }
35
+ .source { (0..3).to_a }
36
+ .source { ('a'..'c').to_a }
37
+ .map { |e| e.collect { |e| e * 2 } }
38
+ .values # or .flatten
17
39
 
18
40
  r
19
- # => %[ aa bb ]
20
- # or
21
- # => %[ bb aa ]
41
+ # => [ 0, 2, 4, 6, 'aa', 'bb', 'cc' ]
42
+ # or
43
+ # => [ 'aa', 'bb', 'cc', 0, 2, 4, 6 ]
22
44
  ```
23
45
 
46
+ Each can be used, the outcome of its block is discarded
24
47
  ```ruby
25
- require 'tresse'
48
+ t = []
49
+ # collecting on the side
26
50
 
27
51
  r =
28
52
  Tresse::Group.new('test0')
29
- .append { [ 'a' ] }
30
- .append { [ 'c' ] }
31
- .append { [ 'b' ] }
32
- .each { |e| e[0] = e[0] * 2 }
33
- .inject([]) { |a, e| a << e.first; a.sort }
53
+ .source { (0..3).to_a }
54
+ .source { ('a'..'c').to_a }
55
+ .each { |e| t << e.collect { |e| e * 2 } }
56
+ .values
34
57
 
35
58
  r
36
- # => %w[ aa bb cc ]
59
+ # => [ 0, 1, 2, 3, 'a', 'b', 'c' ]
60
+ # or
61
+ # => [ 'a', 'b', 'c', 0, 1, 2, 3 ]
62
+
63
+ t
64
+ # => [ [ 0, 2, 4, 6 ], [ 'aa', 'bb', 'cc' ] ]
65
+ # or
66
+ # => [ [ 'aa', 'bb', 'cc' ], [ 0, 2, 4, 6 ] ]
37
67
  ```
38
68
 
69
+
39
70
  ## license
40
71
 
41
72
  MIT, see [LICENSE.txt](LICENSE.txt)
data/lib/tresse.rb CHANGED
@@ -4,27 +4,23 @@ require 'thread'
4
4
 
5
5
  module Tresse
6
6
 
7
- VERSION = '0.1.0'
7
+ VERSION = '1.0.0'
8
8
 
9
9
  class << self
10
10
 
11
- attr_accessor :max_work_threads
12
-
13
11
  def init
14
12
 
15
- @max_work_threads = 7
16
13
  @work_queue = Queue.new
17
- @thread_queue = Queue.new
18
-
19
- @on_error = lambda do |where, err|
20
- puts "-" * 80
21
- p where
22
- p err
23
- puts err.backtrace
24
- puts "-" * 80
25
- end
26
-
27
- run
14
+ @work_threads = 8.times.collect { |i| make_work_thread }
15
+
16
+ @on_error =
17
+ lambda do |where, err|
18
+ puts "-" * 80
19
+ p where
20
+ p err
21
+ puts err.backtrace
22
+ puts "-" * 80
23
+ end
28
24
  end
29
25
 
30
26
  def enqueue(batch)
@@ -39,44 +35,46 @@ module Tresse
39
35
  @on_error = block
40
36
  end
41
37
 
42
- protected
43
-
44
- def run
45
-
46
- @max_work_threads.times { |i| @thread_queue << i }
38
+ def max_work_thread_count
47
39
 
48
- Thread.new do
49
- loop do
50
- begin
40
+ @work_threads.size
41
+ end
51
42
 
52
- i = @thread_queue.pop
53
- batch = @work_queue.pop
43
+ def max_work_thread_count=(i)
54
44
 
55
- hand_to_worker_thread(i, batch)
45
+ i0 = @work_threads.size
56
46
 
57
- rescue => err
47
+ @work_threads << make_work_thread while @work_threads.size < i
48
+ @work_threads.pop while @work_threads.size > i
58
49
 
59
- @on_error.call(:in_loop, err)
60
- end
61
- end
62
- end
50
+ i
63
51
  end
64
52
 
65
- def hand_to_worker_thread(i, batch)
53
+ protected
54
+
55
+ def make_work_thread
66
56
 
67
57
  Thread.new do
68
- begin
69
58
 
70
- Thread.current[:tress] = true
71
- Thread.current[:i] = i
59
+ t = Thread.current
60
+ t[:tresse] = true
72
61
 
73
- batch.process
62
+ loop do
63
+ begin
74
64
 
75
- @thread_queue << i unless i >= @max_work_threads
65
+ batch = @work_queue.pop
76
66
 
77
- rescue => err
67
+ unless @work_threads.include?(t)
68
+ @work_queue << batch
69
+ break
70
+ end
78
71
 
79
- @on_error.call(:in_worker_thread, err)
72
+ batch.process
73
+
74
+ rescue => err
75
+
76
+ @on_error.call(:in_worker_thread, err)
77
+ end
80
78
  end
81
79
  end
82
80
  end
@@ -88,122 +86,153 @@ module Tresse
88
86
  class Batch
89
87
 
90
88
  attr_reader :group
91
- attr_reader :each_index, :value
89
+ attr_reader :map_index
90
+ attr_accessor :value
92
91
 
93
92
  def initialize(group, block_or_group)
94
93
 
95
94
  @group = group
96
95
  @bog = block_or_group
97
96
 
98
- @each_index = -1
97
+ @map_index = -1
99
98
  @value = nil
100
99
  end
101
100
 
102
101
  def process
103
102
 
104
- @each_index += 1
105
- @group.send(:hand, self)
103
+ @map_index += 1
104
+ @group.send(:receive, self)
106
105
  end
107
106
 
108
- protected
109
-
110
- def generate
107
+ def source
111
108
 
112
109
  args = [ group ] + [ nil ] * 7
113
110
  args = args[0, @bog.method(:call).arity]
114
111
 
115
112
  @value = @bog.call(*args)
116
113
  end
114
+
115
+ def map(type, block)
116
+
117
+ args = [ @value, self ]
118
+ args = args[0, block.method(:call).arity.abs]
119
+
120
+ r = block.call(*args)
121
+
122
+ @value = r if type == :map
123
+ end
117
124
  end
118
125
 
119
126
  class Group
120
127
 
121
128
  attr_accessor :name
122
- attr_reader :batches
129
+ #attr_reader :batches
123
130
 
124
- def initialize(name)
131
+ def initialize(name=nil)
125
132
 
126
133
  @name = name
127
134
 
128
135
  @batches = []
129
- @eaches = [ nil ]
136
+ @launched = false
137
+ @maps = [ nil ]
130
138
 
131
- @final = nil
132
- @final_batches = []
133
- @final_queue = Queue.new
139
+ @reduce = nil
140
+ @reduce_batches = []
141
+ @reduction_queue = Queue.new
134
142
  end
135
143
 
136
144
  #
137
- # appending methods
145
+ # sourcing methods
138
146
 
139
- def append(o=nil, &block)
147
+ def source(o=nil, &block)
140
148
 
141
149
  batch = Tresse::Batch.new(self, o ? o : block)
142
150
 
143
151
  @batches << batch
144
- Tresse.enqueue(batch)
152
+
153
+ self
145
154
  end
146
155
 
147
156
  #
148
- # step methods
157
+ # mapping
149
158
 
150
159
  def each(&block)
151
160
 
152
- @eaches << block
161
+ do_map(:each, block)
162
+ end
153
163
 
154
- self
164
+ def map(&block)
165
+
166
+ do_map(:map, block)
155
167
  end
156
168
 
157
169
  #
158
- # final methods
170
+ # reducing
171
+
172
+ def reduce(target, &block)
173
+
174
+ do_reduce(target, block)
175
+ end
176
+ alias inject reduce
159
177
 
160
- def inject(target, &block)
178
+ def flatten
161
179
 
162
- @final = [ target, block ]
180
+ do_reduce([], lambda { |a, e| a.concat(e) })
181
+ end
182
+ alias values flatten
183
+
184
+ protected
185
+
186
+ def do_map(type, block)
163
187
 
164
- @final_queue.pop
188
+ @maps << [ type, block ]
189
+
190
+ launch
191
+
192
+ self
165
193
  end
166
- alias reduce inject
167
194
 
168
- def collect(&block)
195
+ def do_reduce(target, block)
169
196
 
170
- @final = block
197
+ @reduce = [ target, block ]
171
198
 
172
- @final_queue.pop
199
+ launch
200
+
201
+ @reduction_queue.pop
173
202
  end
174
- alias map collect
175
203
 
176
- protected
204
+ def launch
205
+
206
+ return if @launched == true
207
+ @launched = true
177
208
 
178
- def hand(batch)
209
+ @batches.each { |b| Tresse.enqueue(b) }
210
+ end
211
+
212
+ def receive(batch)
179
213
 
180
- if batch.each_index == 0
181
- batch.send(:generate)
214
+ if batch.map_index == 0
215
+ batch.source
182
216
  Tresse.enqueue(batch)
183
- elsif e = @eaches[batch.each_index]
184
- args = [ batch.value, batch ]
185
- args = args[0, e.method(:call).arity.abs]
186
- e.call(*args)
217
+ elsif m = @maps[batch.map_index]
218
+ batch.map(*m)
187
219
  Tresse.enqueue(batch)
188
220
  else
189
- queue_for_final(batch)
221
+ queue_for_reduction(batch)
190
222
  end
191
223
  end
192
224
 
193
- def queue_for_final(batch)
225
+ def queue_for_reduction(batch)
194
226
 
195
- @final_batches << batch
227
+ @reduce_batches << batch
196
228
 
197
- return if @final_batches.size < @batches.size
229
+ return if @reduce_batches.size < @batches.size
230
+ return unless @reduce
198
231
 
199
232
  es = @batches.collect(&:value)
233
+ target, block = @reduce
200
234
 
201
- @final_queue <<
202
- if @final.is_a?(Array)
203
- es.inject(@final[0], &@final[1])
204
- else
205
- es.collect(&@final)
206
- end
235
+ @reduction_queue << es.inject(target, &block)
207
236
  end
208
237
  end
209
238
  end
data/tresse.gemspec CHANGED
@@ -13,10 +13,10 @@ Gem::Specification.new do |s|
13
13
  s.homepage = 'http://github.com/jmettraux/tresse'
14
14
  #s.rubyforge_project = 'rufus'
15
15
  s.license = 'MIT'
16
- s.summary = 'a stupid each+map+reduce thing'
16
+ s.summary = 'a stupid source+map+reduce thing'
17
17
 
18
18
  s.description = %{
19
- a poorly thought out and stupid each+map+reduce contraption
19
+ a poorly thought out and stupid source+map+reduce contraption
20
20
  }.strip
21
21
 
22
22
  #s.files = `git ls-files`.split("\n")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tresse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Mettraux
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-15 00:00:00.000000000 Z
11
+ date: 2019-09-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -24,7 +24,7 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.8'
27
- description: a poorly thought out and stupid each+map+reduce contraption
27
+ description: a poorly thought out and stupid source+map+reduce contraption
28
28
  email:
29
29
  - jmettraux@gmail.com
30
30
  executables: []
@@ -61,5 +61,5 @@ rubyforge_project:
61
61
  rubygems_version: 2.5.2.3
62
62
  signing_key:
63
63
  specification_version: 4
64
- summary: a stupid each+map+reduce thing
64
+ summary: a stupid source+map+reduce thing
65
65
  test_files: []