build-graph 0.1.0 → 0.3.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.
@@ -0,0 +1,133 @@
1
+ //
2
+ // main.cpp
3
+ // DictionarySort
4
+ //
5
+ // Created by Samuel Williams on 31/10/11.
6
+ // Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
7
+ //
8
+
9
+ #include <iostream>
10
+ #include <algorithm>
11
+
12
+ #include "Benchmark.h"
13
+ #include "DictionarySort.h"
14
+
15
+ // Print out vectors using a simple [item0, item1, ... itemn] format.
16
+ template <typename AnyT>
17
+ std::ostream& operator<< (std::ostream &o, const std::vector<AnyT> & v)
18
+ {
19
+ bool first = true;
20
+
21
+ o << "[";
22
+ for (typename std::vector<AnyT>::const_iterator i = v.begin(); i != v.end(); ++i) {
23
+ if (first)
24
+ first = false;
25
+ else
26
+ o << ", ";
27
+
28
+ o << *i;
29
+ }
30
+ o << "]";
31
+
32
+ return o;
33
+ }
34
+
35
+ static void test_parallel_merge ()
36
+ {
37
+ typedef std::vector<long long> ArrayT;
38
+ typedef std::less<long long> ComparatorT;
39
+ ComparatorT comparator;
40
+
41
+ const long long data[] = {
42
+ 2, 4, 6, 8, 12,
43
+ 1, 3, 5, 10, 11
44
+ };
45
+
46
+ ArrayT a(data, data+(sizeof(data)/sizeof(*data)));
47
+ ArrayT b(a.size());
48
+
49
+ ParallelMergeSort::ParallelLeftMerge<ArrayT, ComparatorT> left_merge = {a, b, comparator, 0, a.size() / 2};
50
+ left_merge();
51
+
52
+ std::cout << "After Left: " << b << std::endl;
53
+
54
+ ParallelMergeSort::ParallelRightMerge<ArrayT, ComparatorT> right_merge = {a, b, comparator, 0, a.size() / 2, a.size()};
55
+ right_merge();
56
+
57
+ std::cout << "After Right: " << b << std::endl;
58
+ }
59
+
60
+ static void test_sort ()
61
+ {
62
+ typedef std::vector<long long> ArrayT;
63
+ typedef std::less<long long> ComparatorT;
64
+ ComparatorT comparator;
65
+
66
+ const long long data[] = {
67
+ 11, 2, 4, 6, 8, 10, 12, 1, 3, 5, 7, 9, 13
68
+ };
69
+
70
+ std::vector<long long> v(data, data+(sizeof(data)/sizeof(*data)));
71
+
72
+ std::cerr << "Sorting " << v << std::endl;
73
+
74
+ ParallelMergeSort::sort(v, comparator, 0);
75
+
76
+ std::cerr << "Sorted " << v << std::endl;
77
+ }
78
+
79
+ static void test_dictionary ()
80
+ {
81
+ // This defines a dictionary based on ASCII characters.
82
+ typedef DictionarySort::Dictionary<char, DictionarySort::IndexT[256]> ASCIIDictionaryT;
83
+
84
+ // For unicode characters, you could use something like this:
85
+ // typedef DictionarySort::Dictionary<uint32_t, std::map<uint32_t, DictionarySort::IndexT>> UCS32DictionaryT;
86
+ // Be aware that
87
+
88
+ std::string s = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
89
+ ASCIIDictionaryT::WordT alphabet(s.begin(), s.end());
90
+ ASCIIDictionaryT dictionary(alphabet);
91
+
92
+ ASCIIDictionaryT::WordsT words, sorted_words;
93
+ const std::size_t MAX_LENGTH = 25;
94
+ const std::size_t MAX_COUNT = 2500000;
95
+ for (std::size_t i = 0; i < MAX_COUNT; i += 1) {
96
+ ASCIIDictionaryT::WordT word;
97
+ for (std::size_t j = i; (j-i) <= (i ^ (i * 21)) % MAX_LENGTH; j += 1) {
98
+ word.push_back(alphabet[(j ^ (j << (i % 4))) % alphabet.size()]);
99
+ }
100
+ words.push_back(word);
101
+ }
102
+
103
+ std::cerr << "Sorting " << words.size() << " words..." << std::endl;
104
+ std::cerr << "Sort mode = " << DictionarySort::SORT_MODE << std::endl;
105
+
106
+ if (DictionarySort::SORT_MODE > 0)
107
+ std::cerr << "Parallel merge thread count: " << (1 << (DictionarySort::SORT_MODE+1)) - 2 << std::endl;
108
+
109
+ const int K = 4;
110
+ Benchmark::WallTime t;
111
+ Benchmark::ProcessorTime processor_time;
112
+
113
+ uint64_t checksum;
114
+ for (std::size_t i = 0; i < K; i += 1) {
115
+ checksum = dictionary.sort(words, sorted_words);
116
+ }
117
+ Benchmark::TimeT elapsed_time = t.total() / K;
118
+
119
+ std::cerr << "Checksum: " << checksum << " ? " << (checksum == 479465310674138860) << std::endl;
120
+ std::cerr << "Total Time: " << elapsed_time << std::endl;
121
+
122
+ std::cerr << "Finished." << std::endl;
123
+ }
124
+
125
+ int main (int argc, const char * argv[])
126
+ {
127
+ //test_parallel_merge();
128
+ //test_sort();
129
+ test_dictionary();
130
+
131
+ return 0;
132
+ }
133
+
@@ -0,0 +1 @@
1
+ main.cpp.o: main.cpp Benchmark.h DictionarySort.h ParallelMergeSort.h
Binary file
metadata CHANGED
@@ -1,83 +1,125 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: build-graph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-25 00:00:00.000000000 Z
11
+ date: 2014-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: process-group
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.2.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.2.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: build-files
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
18
32
  - !ruby/object:Gem::Version
19
33
  version: 0.1.0
20
34
  type: :runtime
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
- - - ~>
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: build-makefile
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
25
53
  - !ruby/object:Gem::Version
26
54
  version: 0.1.0
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: system
29
57
  requirement: !ruby/object:Gem::Requirement
30
58
  requirements:
31
- - - '>='
59
+ - - ">="
32
60
  - !ruby/object:Gem::Version
33
61
  version: '0'
34
62
  type: :runtime
35
63
  prerelease: false
36
64
  version_requirements: !ruby/object:Gem::Requirement
37
65
  requirements:
38
- - - '>='
66
+ - - ">="
39
67
  - !ruby/object:Gem::Version
40
68
  version: '0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rainbow
43
71
  requirement: !ruby/object:Gem::Requirement
44
72
  requirements:
45
- - - '>='
73
+ - - "~>"
46
74
  - !ruby/object:Gem::Version
47
- version: '0'
75
+ version: 2.0.0
48
76
  type: :runtime
49
77
  prerelease: false
50
78
  version_requirements: !ruby/object:Gem::Requirement
51
79
  requirements:
52
- - - '>='
80
+ - - "~>"
53
81
  - !ruby/object:Gem::Version
54
- version: '0'
82
+ version: 2.0.0
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: bundler
57
85
  requirement: !ruby/object:Gem::Requirement
58
86
  requirements:
59
- - - ~>
87
+ - - "~>"
60
88
  - !ruby/object:Gem::Version
61
89
  version: '1.3'
62
90
  type: :development
63
91
  prerelease: false
64
92
  version_requirements: !ruby/object:Gem::Requirement
65
93
  requirements:
66
- - - ~>
94
+ - - "~>"
67
95
  - !ruby/object:Gem::Version
68
96
  version: '1.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 3.0.0.rc1
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 3.0.0.rc1
69
111
  - !ruby/object:Gem::Dependency
70
112
  name: rake
71
113
  requirement: !ruby/object:Gem::Requirement
72
114
  requirements:
73
- - - '>='
115
+ - - ">="
74
116
  - !ruby/object:Gem::Version
75
117
  version: '0'
76
118
  type: :development
77
119
  prerelease: false
78
120
  version_requirements: !ruby/object:Gem::Requirement
79
121
  requirements:
80
- - - '>='
122
+ - - ">="
81
123
  - !ruby/object:Gem::Version
82
124
  version: '0'
83
125
  description: "\tBuild::Graph is a framework for managing file-system based build processes.
@@ -89,25 +131,30 @@ executables: []
89
131
  extensions: []
90
132
  extra_rdoc_files: []
91
133
  files:
92
- - .gitignore
93
- - .travis.yml
134
+ - ".gitignore"
135
+ - ".travis.yml"
94
136
  - Gemfile
95
137
  - README.md
96
138
  - Rakefile
97
139
  - build-graph.gemspec
98
- - lib/build.rb
99
- - lib/build/edge.rb
100
- - lib/build/error.rb
101
- - lib/build/files.rb
102
- - lib/build/files/monitor.rb
103
- - lib/build/files/state.rb
104
140
  - lib/build/graph.rb
105
- - lib/build/node.rb
106
- - lib/build/version.rb
107
- - lib/build/walker.rb
108
- - test/program/main.cpp
109
- - test/test_files.rb
110
- - test/test_graph.rb
141
+ - lib/build/graph/controller.rb
142
+ - lib/build/graph/edge.rb
143
+ - lib/build/graph/error.rb
144
+ - lib/build/graph/node.rb
145
+ - lib/build/graph/version.rb
146
+ - lib/build/graph/walker.rb
147
+ - spec/build/graph/graph_spec.rb
148
+ - spec/build/graph/program/Benchmark.cpp
149
+ - spec/build/graph/program/Benchmark.cpp.d
150
+ - spec/build/graph/program/Benchmark.cpp.o
151
+ - spec/build/graph/program/Benchmark.h
152
+ - spec/build/graph/program/DictionarySort.h
153
+ - spec/build/graph/program/ParallelMergeSort.h
154
+ - spec/build/graph/program/dictionary-sort
155
+ - spec/build/graph/program/main.cpp
156
+ - spec/build/graph/program/main.cpp.d
157
+ - spec/build/graph/program/main.cpp.o
111
158
  homepage: ''
112
159
  licenses:
113
160
  - MIT
@@ -118,22 +165,30 @@ require_paths:
118
165
  - lib
119
166
  required_ruby_version: !ruby/object:Gem::Requirement
120
167
  requirements:
121
- - - '>='
168
+ - - ">="
122
169
  - !ruby/object:Gem::Version
123
170
  version: '0'
124
171
  required_rubygems_version: !ruby/object:Gem::Requirement
125
172
  requirements:
126
- - - '>='
173
+ - - ">="
127
174
  - !ruby/object:Gem::Version
128
175
  version: '0'
129
176
  requirements: []
130
177
  rubyforge_project:
131
- rubygems_version: 2.0.3
178
+ rubygems_version: 2.2.2
132
179
  signing_key:
133
180
  specification_version: 4
134
181
  summary: Build::Graph is a framework for build systems, with specific functionality
135
182
  for dealing with file based processes.
136
183
  test_files:
137
- - test/program/main.cpp
138
- - test/test_files.rb
139
- - test/test_graph.rb
184
+ - spec/build/graph/graph_spec.rb
185
+ - spec/build/graph/program/Benchmark.cpp
186
+ - spec/build/graph/program/Benchmark.cpp.d
187
+ - spec/build/graph/program/Benchmark.cpp.o
188
+ - spec/build/graph/program/Benchmark.h
189
+ - spec/build/graph/program/DictionarySort.h
190
+ - spec/build/graph/program/ParallelMergeSort.h
191
+ - spec/build/graph/program/dictionary-sort
192
+ - spec/build/graph/program/main.cpp
193
+ - spec/build/graph/program/main.cpp.d
194
+ - spec/build/graph/program/main.cpp.o
data/lib/build.rb DELETED
@@ -1,5 +0,0 @@
1
- require "build/version"
2
-
3
- module Build
4
-
5
- end
data/lib/build/edge.rb DELETED
@@ -1,49 +0,0 @@
1
-
2
- require 'build/error'
3
-
4
- module Build
5
- # Represents an input to a graph node, with count inputs.
6
- class Edge
7
- def initialize(count = 0)
8
- @fiber = Fiber.current
9
- @count = count
10
-
11
- @failed = []
12
- end
13
-
14
- attr :failed
15
-
16
- attr :fiber
17
- attr :count
18
-
19
- def wait
20
- if @count > 0
21
- Fiber.yield
22
- end
23
-
24
- failed?
25
- end
26
-
27
- attr :failed
28
-
29
- def failed?
30
- @failed.size != 0
31
- end
32
-
33
- def traverse(node)
34
- @count -= 1
35
-
36
- if node.failed?
37
- @failed << node
38
- end
39
-
40
- if @count == 0
41
- @fiber.resume
42
- end
43
- end
44
-
45
- def increment!
46
- @count += 1
47
- end
48
- end
49
- end
data/lib/build/error.rb DELETED
@@ -1,18 +0,0 @@
1
-
2
-
3
- module Build
4
- class TransientError < StandardError
5
- end
6
-
7
- class CommandFailure < TransientError
8
- def initialize(command, status)
9
- super "Command #{command.inspect} failed with exit status #{status}!"
10
-
11
- @command = command
12
- @status = status
13
- end
14
-
15
- attr :command
16
- attr :status
17
- end
18
- end
data/lib/build/files.rb DELETED
@@ -1,286 +0,0 @@
1
- # Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'set'
22
- require 'pathname'
23
-
24
- module Build
25
- module Files
26
- class List
27
- include Enumerable
28
-
29
- def +(list)
30
- Composite.new([self, list])
31
- end
32
-
33
- def intersects? other
34
- other.any?{|path| include?(path)}
35
- end
36
-
37
- def match(pattern)
38
- all? {|path| path.match(pattern)}
39
- end
40
- end
41
-
42
- class RelativePath < String
43
- # Both paths must be full absolute paths, and path must have root as an prefix.
44
- def initialize(path, root)
45
- raise ArgumentError.new("#{root} is not a prefix of #{path}") unless path.start_with?(root)
46
-
47
- super path
48
-
49
- @root = root
50
- end
51
-
52
- attr :root
53
-
54
- def relative_path
55
- self.slice(@root.length..-1)
56
- end
57
- end
58
-
59
- # A list which has a single root directory.
60
- class DirectoryList < List
61
- def initialize(root)
62
- @root = root.to_s
63
- end
64
-
65
- attr :root
66
-
67
- def roots
68
- [@root]
69
- end
70
-
71
- def rebase(root)
72
- raise NotImplementedError
73
- end
74
-
75
- def to_paths(root=@root)
76
- relative_paths = self.each do |path|
77
- path.relative_path
78
- end
79
-
80
- return Paths.new(root, relative_paths)
81
- end
82
-
83
- def process(root=@root)
84
- self.collect do |path|
85
- basename, _, filename = path.relative_path.rpartition(File::SEPARATOR)
86
-
87
- File.join(basename, yield(filename))
88
- end
89
-
90
- Paths.new(root, self.collect)
91
- end
92
- end
93
-
94
- class Directory < DirectoryList
95
- def initialize(root, path = "")
96
- super(root)
97
-
98
- @path = path
99
- end
100
-
101
- attr :path
102
-
103
- def full_path
104
- File.join(@root, @path)
105
- end
106
-
107
- def each(&block)
108
- Dir.glob(full_path + "**/*") do |path|
109
- yield RelativePath.new(path, @root)
110
- end
111
- end
112
-
113
- def eql?(other)
114
- other.kind_of?(self.class) and @root.eql?(other.root) and @path.eql?(other.path)
115
- end
116
-
117
- def hash
118
- [@root, @path].hash
119
- end
120
-
121
- def include?(path)
122
- # Would be true if path is a descendant of full_path.
123
- path.start_with?(full_path)
124
- end
125
-
126
- def rebase(root)
127
- self.class.new(root, @path)
128
- end
129
- end
130
-
131
- class Glob < DirectoryList
132
- def initialize(root, pattern)
133
- super(root)
134
-
135
- @pattern = pattern
136
- end
137
-
138
- attr :root
139
- attr :pattern
140
-
141
- def full_pattern
142
- File.join(@root, @pattern)
143
- end
144
-
145
- # Enumerate all paths matching the pattern.
146
- def each(&block)
147
- Dir.glob(full_pattern) do |path|
148
- yield RelativePath.new(path, @root)
149
- end
150
- end
151
-
152
- def eql?(other)
153
- other.kind_of?(self.class) and @root.eql?(other.root) and @pattern.eql?(other.pattern)
154
- end
155
-
156
- def hash
157
- [@root, @pattern].hash
158
- end
159
-
160
- def include?(path)
161
- File.fnmatch(full_pattern, path)
162
- end
163
-
164
- def rebase(root)
165
- self.class.new(root, @pattern)
166
- end
167
- end
168
-
169
- class Paths < DirectoryList
170
- def initialize(root, paths)
171
- super(root)
172
-
173
- @paths = Array(paths)
174
- end
175
-
176
- attr :paths
177
-
178
- def each(&block)
179
- @paths.each do |path|
180
- full_path = File.join(@root, path)
181
- yield RelativePath.new(full_path, @root)
182
- end
183
- end
184
-
185
- def eql? other
186
- other.kind_of?(self.class) and @paths.eql?(other.paths)
187
- end
188
-
189
- def hash
190
- @paths.hash
191
- end
192
-
193
- def include?(path)
194
- # Compute a full relative path:
195
- full_path = File.absolute_path(path, @root)
196
-
197
- # If the full path starts with @root, test it for inclusion:
198
- if full_path.start_with? @root
199
- # Compute the relative component:
200
- relative_path = full_path[@root.length..-1]
201
-
202
- # Does this list of paths include it?
203
- return @paths.include?(relative_path)
204
- else
205
- return false
206
- end
207
- end
208
-
209
- def rebase(root)
210
- self.class.new(root, @paths)
211
- end
212
-
213
- def to_paths
214
- return self
215
- end
216
- end
217
-
218
- class Composite < List
219
- def initialize(files = Set.new)
220
- @files = files
221
- end
222
-
223
- attr :files
224
-
225
- def each(&block)
226
- @files.each do |files|
227
- files.each &block
228
- end
229
- end
230
-
231
- def roots
232
- @files.collect(&:roots).flatten.uniq
233
- end
234
-
235
- def eql?(other)
236
- other.kind_of?(self.class) and @files.eql?(other.files)
237
- end
238
-
239
- def hash
240
- @files.hash
241
- end
242
-
243
- def merge(list)
244
- if list.kind_of? Composite
245
- @files += list.files
246
- elsif list.kind_of? List
247
- @files << list
248
- else
249
- raise ArgumentError.new("Cannot merge non-list of file paths.")
250
- end
251
- end
252
-
253
- def +(list)
254
- if list.kind_of? Composite
255
- Composite.new(@files + list.files)
256
- else
257
- Composite.new(@files + [list])
258
- end
259
- end
260
-
261
- def include?(path)
262
- @files.any? {|list| list.include?(path)}
263
- end
264
-
265
- def rebase(root)
266
- self.class.new(@files.collect{|list| list.rebase(root)})
267
- end
268
-
269
- def to_paths
270
- Composite.new(@files.collect(&:to_paths))
271
- end
272
-
273
- def self.[](files)
274
- if files.size == 0
275
- return None
276
- elsif files.size == 1
277
- files.first
278
- else
279
- self.class.new(files)
280
- end
281
- end
282
- end
283
-
284
- NONE = Composite.new
285
- end
286
- end