tresse 0.1.0 → 1.0.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.
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: []