go 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ /.idea
2
+ /pkg
3
+ *.sublime*
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2011 Travis Reeder, Appoxy LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,94 @@
1
+ # Go - A concurrency library for Ruby inspired by Go (golang).
2
+
3
+ ## Getting Started
4
+
5
+ Install gem:
6
+
7
+ ```
8
+ gem install go
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Basic
14
+
15
+ ```ruby
16
+ require 'go'
17
+
18
+ # set max threads (optional)
19
+ Go.config.max_threads = 10
20
+
21
+ # fire off blocks using go
22
+ 100.times do |i|
23
+ go do
24
+ puts "hello #{i}"
25
+ sleep 1
26
+ puts "#{i} awoke"
27
+ puts "hi there"
28
+ end
29
+ puts "done #{i}"
30
+ end
31
+ ```
32
+
33
+ ### Use channels to communicate
34
+
35
+ ```ruby
36
+ require 'go'
37
+
38
+ # Use channels to communicate
39
+ ch = Go::Channel.new
40
+ 20.times do |i|
41
+ go do
42
+ puts "hello channel #{i} #{ch}"
43
+ sleep 2
44
+ # push to channel
45
+ ch << "pushed #{i} to channel"
46
+ end
47
+ end
48
+
49
+ # Read from channel
50
+ ch.each do |x|
51
+ puts "Got #{x} from channel"
52
+ end
53
+ ```
54
+
55
+ ### Catching exceptions and checking for different return types on the channel
56
+
57
+ ```ruby
58
+ require 'go'
59
+
60
+ # Use channels to communicate
61
+ ch = Go::Channel.new
62
+ 20.times do |i|
63
+ go do
64
+ begin
65
+ puts "hello channel #{i}"
66
+ ch << "pushed #{i} to channel"
67
+ rescue => ex
68
+ ch << ex
69
+ end
70
+ end
71
+ end
72
+
73
+ # Read from channel
74
+ ch.each do |m|
75
+ puts "Got #{m} from channel"
76
+ case m
77
+ when String
78
+ puts m
79
+ when Exception
80
+ puts "ERROR!!! #{m}"
81
+ else
82
+ puts "Something else: #{m}"
83
+ end
84
+ end
85
+ ```
86
+
87
+ ### Closing the channel
88
+
89
+ You can close the channel with the close() method which will stop all the listeners on the channel.
90
+
91
+ ```ruby
92
+ ch.close()
93
+ ```
94
+
@@ -0,0 +1,5 @@
1
+ Rake::TestTask.new do |t|
2
+ t.libs << "test"
3
+ t.test_files = FileList['test/test*.rb']
4
+ t.verbose = true
5
+ end
@@ -0,0 +1,25 @@
1
+
2
+ require File.expand_path('../lib/go/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Travis Reeder"]
6
+ gem.email = ["treeder@gmail.com"]
7
+ gem.description = "A concurrency library for Ruby inspired by Go (golang)."
8
+ gem.summary = "A concurrency library for Ruby inspired by Go (golang)."
9
+ gem.homepage = "https://github.com/treeder/go"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "go"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Go::VERSION
17
+
18
+ gem.required_rubygems_version = ">= 1.3.6"
19
+ gem.required_ruby_version = Gem::Requirement.new(">= 1.9")
20
+
21
+ gem.add_runtime_dependency "concur"
22
+
23
+ gem.add_development_dependency "test-unit"
24
+
25
+ end
@@ -0,0 +1,25 @@
1
+ require 'logger'
2
+ require 'concur'
3
+
4
+ require_relative 'go/version'
5
+ require_relative 'go/config'
6
+ require_relative 'go/channel'
7
+ require_relative 'go/kernel'
8
+
9
+ module Go
10
+ @@logger = Logger.new(STDOUT)
11
+ @@logger.level = Logger::INFO
12
+ @@config = Config.new
13
+
14
+ def self.logger
15
+ @@logger
16
+ end
17
+ def self.logger=(logger)
18
+ @@logger = logger
19
+ end
20
+
21
+ def self.config
22
+ @@config ||= Config.new
23
+ end
24
+
25
+ end
@@ -0,0 +1,51 @@
1
+ module Go
2
+ class Channel
3
+ attr_reader :closed
4
+
5
+ def initialize
6
+ @queue = Queue.new
7
+ end
8
+
9
+ def <<(ob)
10
+ @queue << ob
11
+ end
12
+
13
+ def shift
14
+ begin
15
+ @queue.shift
16
+ rescue Exception => ex
17
+ puts ex.class.name
18
+ p ex
19
+ puts ex.message
20
+ if ex.class.name == "fatal" && ex.message.include?("deadlock")
21
+ close()
22
+ return Go::Exit
23
+ end
24
+ raise ex
25
+ end
26
+ end
27
+
28
+ def each(&blk)
29
+ while true do
30
+ puts "Closed? #{@closed}"
31
+ break if @closed
32
+ x = shift
33
+ break if x == Go::Exit
34
+ yield x
35
+ end
36
+ end
37
+
38
+ # close the channel
39
+ def close
40
+ puts 'closing channel'
41
+ @closed = true
42
+ self << Go::Exit
43
+ end
44
+ end
45
+
46
+ # Just for exiting a channel
47
+ class Exit
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,36 @@
1
+ module Go
2
+ class Config
3
+ attr_reader :defaults
4
+
5
+ def initialize(options={})
6
+ init_defaults
7
+ @listeners = []
8
+ @max_threads = options[:max_threads] || defaults[:max_threads]
9
+ end
10
+
11
+ def init_defaults
12
+ @defaults = {
13
+ max_threads: 20
14
+ }
15
+ end
16
+
17
+ def max_threads=(x)
18
+ @max_threads = x
19
+ notify_listeners(:max_threads=>x)
20
+ end
21
+
22
+ def max_threads
23
+ @max_threads
24
+ end
25
+
26
+ def add_listener(l)
27
+ @listeners << l
28
+ end
29
+
30
+ def notify_listeners(changes)
31
+ @listeners.each do |l|
32
+ l.update(changes)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+
2
+ module Go
3
+ class GoKernel
4
+ def initialize(config)
5
+ @config = config
6
+ @executor = Concur::Executor.new_thread_pool_executor(@config.max_threads)
7
+ @config.add_listener(@executor)
8
+ end
9
+
10
+ def executor
11
+ @executor
12
+ end
13
+ end
14
+
15
+ def self.gok
16
+ @gok ||= GoKernel.new(Go.config)
17
+ end
18
+
19
+ end
20
+
21
+ module ::Kernel
22
+ def go(ch=nil, &blk)
23
+ future = ::Go.gok.executor.execute(nil, ch, &blk)
24
+ future
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module Go
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,92 @@
1
+ gem 'test-unit'
2
+ require 'test/unit'
3
+ require_relative '../lib/go'
4
+
5
+ class TestGo < Test::Unit::TestCase
6
+
7
+ def test_go
8
+
9
+ Go.config.max_threads = 10
10
+
11
+ 3.times do |i|
12
+ go do
13
+ puts "#{i} sleeping..."
14
+ sleep 1
15
+ puts "#{i} awoke"
16
+ end
17
+ puts "#{i} done "
18
+ end
19
+
20
+ ch = Go::Channel.new
21
+ times = 10
22
+ times.times do |i|
23
+ go do
24
+ #puts "hello channel #{i}"
25
+ sleep 1
26
+ # push to channel
27
+ ch << "hello, I am # #{i}"
28
+ end
29
+ end
30
+
31
+ puts "waiting on channel..."
32
+ i = 0
33
+ ch.each do |x|
34
+ puts "Got: #{x}"
35
+ i += 1
36
+ end
37
+ assert_equal times, i
38
+
39
+ # Pass different objects back
40
+ ch = Go::Channel.new
41
+ times = 10
42
+ errmod = 5
43
+ times.times do |i|
44
+ go do
45
+ begin
46
+ raise "Error yo!" if i % errmod == 0
47
+ puts "hello channel #{i}"
48
+ sleep 1
49
+ # push to channel
50
+ ch << "pushed #{i} to channel"
51
+ rescue => ex
52
+ ch << ex
53
+ end
54
+ end
55
+ end
56
+
57
+ go do
58
+ # wait for a bit, then close channel
59
+ sleep 10
60
+ ch.close
61
+ end
62
+
63
+ puts "waiting on channel..."
64
+ i = 0
65
+ errs = 0
66
+ ch.each do |x|
67
+ puts "Got #{x} from channel"
68
+ i += 1
69
+ case x
70
+ when String
71
+ puts "Is String"
72
+ when Exception
73
+ puts "Is Exception!"
74
+ errs += 1
75
+ when nil
76
+ puts "got nil, breaking"
77
+ break
78
+ else
79
+ puts "Is something else"
80
+ end
81
+ end
82
+ assert_equal times, i
83
+ assert_equal times / errmod, errs
84
+ puts 'donezo'
85
+
86
+ end
87
+
88
+
89
+ end
90
+
91
+
92
+
metadata CHANGED
@@ -1,66 +1,89 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: go
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 1
9
- version: 0.0.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
12
- - Florent Guilleux
13
- - Alvaro Pereyra
7
+ authors:
8
+ - Travis Reeder
14
9
  autorequire:
15
10
  bindir: bin
16
- cert_chain:
17
- date: 2010-04-13 00:00:00 -05:00
18
- default_executable: go
19
- dependencies: []
20
-
21
- description: A script to launch commands in differents iTerm tabs for a Rails project. inspired by http://github.com/chrisjpowers/iterm_window examples.
22
- email: alvaro@xendacentral.com
11
+ cert_chain: []
12
+ date: 2013-02-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: concur
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: test-unit
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: A concurrency library for Ruby inspired by Go (golang).
47
+ email:
48
+ - treeder@gmail.com
23
49
  executables: []
24
-
25
50
  extensions: []
26
-
27
51
  extra_rdoc_files: []
28
-
29
- files:
30
- - README.markdown
31
- - iterm_rails.gemspec
32
- - iterm_rails.rb
33
- - lib/iterm_rails.rb
34
- has_rdoc: true
35
- homepage: http://github.com/xenda/iterm-rails
52
+ files:
53
+ - .gitignore
54
+ - LICENSE.md
55
+ - README.md
56
+ - Rakefile
57
+ - go.gemspec
58
+ - lib/go.rb
59
+ - lib/go/channel.rb
60
+ - lib/go/config.rb
61
+ - lib/go/kernel.rb
62
+ - lib/go/version.rb
63
+ - test/test_go.rb
64
+ homepage: https://github.com/treeder/go
36
65
  licenses: []
37
-
38
66
  post_install_message:
39
67
  rdoc_options: []
40
-
41
- require_paths:
68
+ require_paths:
42
69
  - lib
43
- required_ruby_version: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ~>
46
- - !ruby/object:Gem::Version
47
- segments:
48
- - 1
49
- - 9
50
- version: "1.9"
51
- required_rubygems_version: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- segments:
56
- - 0
57
- version: "0"
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '1.9'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: 1.3.6
58
82
  requirements: []
59
-
60
83
  rubyforge_project:
61
- rubygems_version: 1.3.6
84
+ rubygems_version: 1.8.25
62
85
  signing_key:
63
86
  specification_version: 3
64
- summary: A script to launch commands in differents iTerm tabs for a Rails project
65
- test_files: []
66
-
87
+ summary: A concurrency library for Ruby inspired by Go (golang).
88
+ test_files:
89
+ - test/test_go.rb
@@ -1,42 +0,0 @@
1
- GO - Iterm-Rails
2
- ===================
3
-
4
- A script to launch commands in differents iTerm tabs for a Rails project: console, server, mate...
5
- inspired by http://github.com/chrisjpowers/iterm_window examples
6
-
7
- Examples:
8
- --------------
9
-
10
- iterm-rails /path/to/project
11
-
12
- iterm-rails project # you can set a default project directory (see configuration options below)
13
-
14
-
15
- Configuration:
16
- --------------
17
- You can override default configuration options:
18
-
19
- - globally in ~/.iterm-rails.config
20
-
21
- - per project in project/.iterm-rails.config
22
-
23
-
24
- Configuration options in DEFAULT_CONFIG:
25
- ----------------------------------------
26
-
27
- DEFAULT_CONFIG = {
28
- :projects_dir => Dir.getwd,
29
- :launch_server => true,
30
- :launch_console => true,
31
- :launch_spork_for_rspec => false,
32
- :launch_spork_for_cuc => false,
33
- :rails3 => false,
34
- :prepend_command => nil, # example: 'rvm ruby-1.9.2-head'
35
- }
36
-
37
- Author
38
- ------
39
-
40
- - Florent Guilleux (Author): github.com/Florent2 | florent2 AT gmail DOT com
41
-
42
- - Alvaro Pereyra (Contributor): github.com/xenda | alvaro AT xendacentral DOT com
@@ -1,35 +0,0 @@
1
- #!/usr/bin/env gem build
2
- # encoding: utf-8
3
-
4
- require "base64"
5
-
6
- Gem::Specification.new do |s|
7
- s.name = "go"
8
- s.version = "0.0.1"
9
- s.authors = ["Florent Guilleux", "Alvaro Pereyra"]
10
- s.homepage = "http://github.com/xenda/iterm-rails"
11
- s.summary = "A script to launch commands in differents iTerm tabs for a Rails project"
12
- s.description = "#{s.summary}. inspired by http://github.com/chrisjpowers/iterm_window examples."
13
- s.cert_chain = nil
14
- s.email = Base64.decode64("YWx2YXJvQHhlbmRhY2VudHJhbC5jb20=\n")
15
- s.has_rdoc = false
16
-
17
- # files
18
- s.files = `git ls-files`.split("\n")
19
-
20
- Dir["bin/*"].map(&File.method(:basename))
21
- s.default_executable = "go"
22
- s.require_paths = ["lib"]
23
-
24
- # Ruby version
25
- s.required_ruby_version = ::Gem::Requirement.new("~> 1.9")
26
-
27
- begin
28
- require "changelog"
29
- rescue LoadError
30
- warn "You have to have changelog gem installed for post install message"
31
- else
32
- s.post_install_message = CHANGELOG.new.version_changes
33
- end
34
-
35
- end
@@ -1 +0,0 @@
1
- require "iterm_rails"
@@ -1,130 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # a script to launch commands in differents iTerm tabs for a Rails project: console, server, mate...
4
- # inspired by http://github.com/chrisjpowers/iterm_window examples
5
-
6
- # examples:
7
- # iterm-rails /path/to/project
8
- # iterm-rails project # you can set a default project directory (see configuration options below)
9
-
10
- # you can override default configuration options:
11
- # globally in ~/.iterm-rails.config
12
- # per project in project/.iterm-rails.config
13
- # see configuration options in DEFAULT_CONFIG below
14
-
15
-
16
- require 'rubygems'
17
- require 'iterm_window'
18
- require 'pathname'
19
- require 'yaml'
20
- require 'socket'
21
- require 'timeout'
22
-
23
- module ItermRails
24
-
25
- DEFAULT_CONFIG = {
26
- :projects_dir => Dir.getwd,
27
- :launch_server => true,
28
- :launch_console => true,
29
- :launch_spork_for_rspec => false,
30
- :launch_spork_for_cuc => false,
31
- :rails3 => false,
32
- :prepend_command => nil, # example: 'rvm ruby-1.9.2-head'
33
- }
34
-
35
- def create_tab(project_path, *commands)
36
- project_name = project_path.basename
37
- open_tab :new_tab do
38
- write "cd #{project_path}"
39
- set_title "- #{project_name}"
40
- end
41
- end
42
-
43
- def find_available_port_from(port_number)
44
- result = port_number
45
- result += 1 while is_port_open?(result)
46
- result
47
- end
48
-
49
- def is_a_rails_project_directory?(project_path)
50
- %w{app config db script}.all? { |directory| project_path.join(directory).exist? }
51
- end
52
-
53
- # from http://stackoverflow.com/questions/517219/ruby-see-if-a-port-is-open
54
- def is_port_open?(port_number)
55
- begin
56
- Timeout::timeout(1) do
57
- begin
58
- s = TCPSocket.new('localhost', port_number)
59
- s.close
60
- return true
61
- rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
62
- return false
63
- end
64
- end
65
- rescue Timeout::Error
66
- end
67
-
68
- return false
69
- end
70
-
71
- def merge_configs(config, custom_config_file_path)
72
- if custom_config_file_path.exist?
73
- config.merge YAML::load(File.open custom_config_file_path)
74
- else
75
- config
76
- end
77
- end
78
-
79
- config = merge_configs DEFAULT_CONFIG, Pathname.new('~').expand_path.join('.iterm-rails.config')
80
-
81
- raise "missing project path" if ARGV.first.nil?
82
- project_path = Pathname.new ARGV.first
83
- project_path = Pathname.new(config[:projects_dir]).join(project_path) if project_path.relative?
84
- project_path = project_path.expand_path
85
- raise "'#{project_path}' does not exist or is not a directory" if !project_path.directory?
86
- raise "'#{project_path}' is not a Rails project directory" if !is_a_rails_project_directory?(project_path)
87
- config = merge_configs config, project_path.join('.iterm-rails.config')
88
-
89
- puts "open new window with tabs for '#{project_path}'"
90
- puts " with config: #{config.inspect}"
91
-
92
- Tab = Struct.new :title, :commands
93
- tabs = []
94
-
95
- if config[:launch_spork_for_rspec]
96
- port = find_available_port_from 8989
97
- tabs << Tab.new("spork #{port}", ["spork -p #{port}"])
98
- end
99
-
100
- if config[:launch_spork_for_cuc]
101
- port = find_available_port_from 9989
102
- tabs << Tab.new("spork cuc #{port}", ["spork cuc -p #{port}"])
103
- end
104
-
105
- if config[:launch_console]
106
- command = if config[:rails3] then "rails console" else "script/console" end
107
- tabs << Tab.new("console", [command])
108
- end
109
-
110
- tabs << Tab.new("main", ["mate ./ &"])
111
-
112
- if config[:launch_console]
113
- port = find_available_port_from 3000
114
- command = if config[:rails3] then "rails server" else "script/server" end
115
- tabs << Tab.new("server #{port}", ["#{command} -p #{port}"])
116
- end
117
-
118
- ItermWindow.open do
119
- project_name = project_path.basename
120
- tabs.each do |tab|
121
- open_tab :new_tab do
122
- write "cd #{project_path}"
123
- write config[:prepend_command] unless config[:prepend_command] == "nil" || config[:prepend_command].empty?
124
- tab.commands.each { |command| write command }
125
- set_title "#{tab.title} - #{project_name}"
126
- end
127
- end
128
- end
129
-
130
- end