the_force 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2010 Symbolforce, LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.rdoc ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ require 'rake'
2
+
3
+ include_file_globs = ['README.rdoc', 'LICENSE', 'Rakefile', 'init.rb', '{lib}/**/*']
4
+ exclude_file_globs = []
5
+
6
+ spec = Gem::Specification.new do |s|
7
+ s.name = "the_force"
8
+ s.version = '0.0.1'
9
+ s.author = "Ryan Ziegler"
10
+ s.email = "info@symbolforce.com"
11
+ s.homepage = "http://www.symbolforce.com"
12
+ s.platform = Gem::Platform::RUBY
13
+ s.summary = "Common code for Symbolforce"
14
+ s.description = "Common code for Symbolforce"
15
+ s.files = FileList[include_file_globs].to_a - FileList[exclude_file_globs].to_a
16
+ s.require_path = "lib"
17
+ s.test_files = FileList["test/**/test_*.rb"].to_a
18
+ # s.has_rdoc = true
19
+ s.extra_rdoc_files = FileList["README*"].to_a
20
+ s.rdoc_options << '--line-numbers' << '--inline-source'
21
+ end
22
+
23
+ desc "Generate gemspec for gemcutter"
24
+ task :gemspec => :clean do
25
+ File.open("#{spec.name}.gemspec", 'w') do |f|
26
+ f.write spec.to_ruby
27
+ end
28
+ end
29
+
30
+ desc 'Clean up files.'
31
+ task :clean do
32
+ FileUtils.rm "*.gemspec" rescue nil
33
+ FileUtils.rm "the_force-0.0.1.gem" rescue nil
34
+ end
35
+
36
+ desc 'Default, do nothing'
37
+ task :default do
38
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), "lib", "the_force")
@@ -0,0 +1,26 @@
1
+ require 'system_timer'
2
+
3
+ #CRZ - :exceptions uses is_a? not instance_of?
4
+ module TheForce
5
+ def self.keep_trying(times = 3, options = {}, &b)
6
+ options = {:exceptions => [StandardError], :timeout => false}.merge(options)
7
+ options[:exceptions] = [options[:exceptions]] unless options[:exceptions].is_a? Array
8
+ options[:exceptions] << Timeout::Error if options[:timeout]
9
+
10
+ try = 0;
11
+ loop do
12
+ begin
13
+ try += 1
14
+ if options[:timeout]
15
+ SystemTimer.timeout_after(options[:timeout]) do
16
+ return yield(try)
17
+ end
18
+ else
19
+ return yield(try)
20
+ end
21
+ rescue Exception => e
22
+ raise if (try >= times) or not options[:exceptions].any? {|exception| e.is_a? exception}
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,108 @@
1
+ require 'thread'
2
+ begin
3
+ require 'fasttread'
4
+ rescue LoadError
5
+ $stderr.puts "Using the ruby-core thread implementation"
6
+ end
7
+
8
+ module TheForce
9
+ class ThreadPool
10
+ class Worker
11
+ def initialize(thread_queue)
12
+ @mutex = Mutex.new
13
+ @cv = ConditionVariable.new
14
+ @queue = thread_queue
15
+ @running = true
16
+ @thread = Thread.new do
17
+ @mutex.synchronize do
18
+ while @running
19
+ @cv.wait(@mutex)
20
+ block = get_block
21
+ if block
22
+ @mutex.unlock
23
+ block.call
24
+ @mutex.lock
25
+ reset_block
26
+ end
27
+ @queue << self
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ def name
34
+ @thread.inspect
35
+ end
36
+
37
+ def get_block
38
+ @block
39
+ end
40
+
41
+ def set_block(block)
42
+ @mutex.synchronize do
43
+ raise RuntimeError, "Thread already busy." if @block
44
+ @block = block
45
+ # Signal the thread in this class, that there's a job to be done
46
+ @cv.signal
47
+ end
48
+ end
49
+
50
+ def reset_block
51
+ @block = nil
52
+ end
53
+
54
+ def busy?
55
+ @mutex.synchronize { !@block.nil? }
56
+ end
57
+
58
+ def stop
59
+ @mutex.synchronize do
60
+ @running = false
61
+ @cv.signal
62
+ end
63
+ @thread.join
64
+ end
65
+ end
66
+
67
+ attr_accessor :max_size
68
+
69
+ def initialize(max_size = 10)
70
+ @max_size = max_size
71
+ @queue = Queue.new
72
+ @workers = []
73
+ end
74
+
75
+ def size
76
+ @workers.size
77
+ end
78
+
79
+ def busy?
80
+ @queue.size < @workers.size
81
+ end
82
+
83
+ def shutdown
84
+ @workers.each { |w| w.stop }
85
+ @workers = []
86
+ end
87
+
88
+ alias :join :shutdown
89
+
90
+ def process(block=nil,&blk)
91
+ block = blk if block_given?
92
+ worker = get_worker
93
+ worker.set_block(block)
94
+ end
95
+
96
+ private
97
+
98
+ def get_worker
99
+ if !@queue.empty? or @workers.size == @max_size
100
+ return @queue.pop
101
+ else
102
+ worker = Worker.new(@queue)
103
+ @workers << worker
104
+ worker
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,80 @@
1
+ #CRZ - Have been thinking making this something you mixin...that may solve the binding issue in self.timer...
2
+ #CRZ - or just make Timer a class and you create it and then start/stop etc...multiple timers at once?
3
+ # - lets wait til I need to do that
4
+
5
+ ###CRZ - just use the benchmark module...this is redundant
6
+
7
+ module TheForce
8
+ module Timer
9
+ @timers = []
10
+ @timer_depth = 0
11
+
12
+ #CRZ - for mixin; expects just a symbol and list of args
13
+ # - helps solve passing symbol problem
14
+ def timer(*args, &b);
15
+ if block_given?
16
+ Force::Timer.timer(*args, &b)
17
+ else
18
+ Force::Timer.timer args[0] do
19
+ send(args.shift, *args)
20
+ end
21
+ end
22
+ end
23
+ def report_timers(*args); Force::Timer.report_timers(*args); end
24
+
25
+ # CRZ - totally not thread coherent, but still useful
26
+ # - I wanted to allow you to pass in a symbol which was the method to time...but when I send(symbol) from inside this module,
27
+ # the method loses its binding. for example, a method in another class which you time now wouldnt havent access to its
28
+ # instance variables...
29
+ def self.timer(*args)
30
+ name = args.shift if args.length > 0
31
+
32
+ puts "TIMER #{name || ""} starting..."
33
+ @timer_depth += 1
34
+ start_time = Time.now
35
+ yield
36
+ end_time = Time.now
37
+ @timer_depth -= 1
38
+ puts "TIMER #{name || ""} ended: #{seconds_to_time(end_time - start_time)} elapsed"
39
+
40
+ @timers << [name || "", (end_time - start_time), @timer_depth]
41
+ end
42
+
43
+ def self.report_timers
44
+ puts
45
+ puts "-- TIMER REPORT IN ORDER OF timer METHOD *FINISHING*, NOT STARTING --"
46
+ @timers.each do |x|
47
+ puts "#{' ' * x[2]}#{x[0].to_s.ljust(50-(2*x[2]), " ")} : #{seconds_to_time(x[1])}"
48
+ end
49
+ puts
50
+ end
51
+
52
+ ###CRZ - might be nice to metaprogrammize and auto wrap the list of methods
53
+ #def assign_timer(*methods)
54
+ #end
55
+
56
+ private
57
+ #CRZ - prints a minimal string of type 1d1h1m1.001s
58
+ # - always prints seconds, but won't print other units of time unless they are relevant
59
+ # - hard to make this pretty...too many special cases; isn't this built already somewhere?
60
+ def self.seconds_to_time(secs)
61
+ units, suffixes, widths = [86400000, 3600000, 60000, 1000, 1], %w(d h m . s), [0,0,0,0,3]
62
+
63
+ rest, times = (secs * 1000).to_i, [] #start with millis
64
+ units.each do |x|
65
+ times << (rest / x)
66
+ rest %= x
67
+ end
68
+
69
+ time, started = "", false
70
+ suffixes.each_with_index do |x, i|
71
+ next if times[i] == 0 and not started and not i == (suffixes.length - 2)
72
+
73
+ started = true
74
+ time += times[i].to_s.rjust(widths[i], '0') + x
75
+ end
76
+
77
+ time
78
+ end
79
+ end
80
+ end
data/lib/the_force.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'the_force/keep_trying'
2
+ require 'the_force/timer'
3
+ require 'the_force/thread_pool'
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: the_force
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Ziegler
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-19 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Common code for Symbolforce
17
+ email: info@symbolforce.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ files:
25
+ - README.rdoc
26
+ - LICENSE
27
+ - Rakefile
28
+ - init.rb
29
+ - lib/the_force/keep_trying.rb
30
+ - lib/the_force/thread_pool.rb
31
+ - lib/the_force/timer.rb
32
+ - lib/the_force.rb
33
+ has_rdoc: true
34
+ homepage: http://www.symbolforce.com
35
+ licenses: []
36
+
37
+ post_install_message:
38
+ rdoc_options:
39
+ - --line-numbers
40
+ - --inline-source
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ requirements: []
56
+
57
+ rubyforge_project:
58
+ rubygems_version: 1.3.5
59
+ signing_key:
60
+ specification_version: 3
61
+ summary: Common code for Symbolforce
62
+ test_files: []
63
+