keeper 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.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1,5 @@
1
+ --color
2
+ -fs
3
+ -Ilib
4
+ -Ispec
5
+ --require spec_helper
@@ -0,0 +1,3 @@
1
+ --title "Keeper"
2
+ --charset UTF-8
3
+ --markup markdown
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+
3
+ group :development do
4
+ gem "rspec", "~> 2.1.0"
5
+ gem "yard", "~> 0.6.0"
6
+ gem "bluecloth"
7
+ gem "bundler", "~> 1.0.0"
8
+ gem "jeweler", "~> 1.5.1"
9
+ end
@@ -0,0 +1,30 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ bluecloth (2.0.9)
5
+ diff-lcs (1.1.2)
6
+ git (1.2.5)
7
+ jeweler (1.5.1)
8
+ bundler (~> 1.0.0)
9
+ git (>= 1.2.5)
10
+ rake
11
+ rake (0.8.7)
12
+ rspec (2.1.0)
13
+ rspec-core (~> 2.1.0)
14
+ rspec-expectations (~> 2.1.0)
15
+ rspec-mocks (~> 2.1.0)
16
+ rspec-core (2.1.0)
17
+ rspec-expectations (2.1.0)
18
+ diff-lcs (~> 1.1.2)
19
+ rspec-mocks (2.1.0)
20
+ yard (0.6.3)
21
+
22
+ PLATFORMS
23
+ ruby
24
+
25
+ DEPENDENCIES
26
+ bluecloth
27
+ bundler (~> 1.0.0)
28
+ jeweler (~> 1.5.1)
29
+ rspec (~> 2.1.0)
30
+ yard (~> 0.6.0)
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Kim Burgestrand
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,45 @@
1
+ Keeper!?
2
+ ========
3
+ Ever wished you could spawn several threads, each of them waiting for a certain event to happen, without having to do the manual book-keeping of condition variables and mutexes? Now you can!
4
+
5
+ Keeper is a library that allows multiple threads to wait for incoming events. Have a look at this example code from the docs:
6
+
7
+ events = Keeper::Keeper.new
8
+
9
+ [:pang, :boom, :pow].each_with_index do |event, i|
10
+ this_many = i + 1
11
+ this_many.times do |i|
12
+ Thread.new do
13
+ events.wait_for(event)
14
+ puts "#{event}:#{i}!"
15
+ events.fire(event == :pang ? :boom : :pow)
16
+ end
17
+ end
18
+ puts "#{this_many} threads waiting for #{event}"
19
+ end
20
+
21
+ print "Pause for effect"
22
+ 3.times { sleep 1 and print "." }
23
+ puts
24
+
25
+ events.fire(:pang)
26
+ Thread.list.reject { |th| th == Thread.current }.map(&:join)
27
+
28
+ And here’s your output:
29
+
30
+ 1 threads waiting for pang
31
+ 2 threads waiting for boom
32
+ 3 threads waiting for pow
33
+ Pause for effect...
34
+ pang:0!
35
+ boom:0!
36
+ boom:1!
37
+ pow:0!
38
+ pow:2!
39
+ pow:1!
40
+
41
+ Ain’t that awesome?! I think it is.
42
+
43
+ License
44
+ -------
45
+ X11. It means you can use Keeper for whatever you want as long as you ship the license text with it, it’s in LICENSE.txt.
@@ -0,0 +1,31 @@
1
+ require 'bundler'
2
+ begin
3
+ Bundler.setup(:default, :development)
4
+ rescue Bundler::BundlerError => e
5
+ $stderr.puts e.message
6
+ $stderr.puts "Run `bundle install` to install missing gems"
7
+ exit e.status_code
8
+ end
9
+ require 'rake'
10
+ require 'yard'
11
+ require 'jeweler'
12
+ require 'rspec/core/rake_task'
13
+ require './lib/keeper/version'
14
+
15
+ Jeweler::Tasks.new do |gem|
16
+ gem.name = "keeper"
17
+ gem.homepage = "http://github.com/Burgestrand/keeper"
18
+ gem.license = "X11"
19
+
20
+ gem.summary = %Q{A thread-safe blocking event pattern for your pleasure.}
21
+ gem.authors = ["Kim Burgestrand"]
22
+ gem.email = "kim@burgestrand.se"
23
+
24
+ gem.version = Keeper::Version::STRING
25
+ end
26
+
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+ YARD::Rake::YardocTask.new
29
+ RSpec::Core::RakeTask.new
30
+
31
+ task :default => :spec
@@ -0,0 +1,68 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{keeper}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Kim Burgestrand"]
12
+ s.date = %q{2010-12-11}
13
+ s.email = %q{kim@burgestrand.se}
14
+ s.extra_rdoc_files = [
15
+ "LICENSE.txt",
16
+ "README.markdown"
17
+ ]
18
+ s.files = [
19
+ ".document",
20
+ ".rspec",
21
+ ".yardopts",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE.txt",
25
+ "README.markdown",
26
+ "Rakefile",
27
+ "keeper.gemspec",
28
+ "lib/keeper.rb",
29
+ "lib/keeper/version.rb",
30
+ "spec/keeper_spec.rb",
31
+ "spec/spec_helper.rb"
32
+ ]
33
+ s.homepage = %q{http://github.com/Burgestrand/keeper}
34
+ s.licenses = ["X11"]
35
+ s.require_paths = ["lib"]
36
+ s.rubygems_version = %q{1.3.7}
37
+ s.summary = %q{A thread-safe blocking event pattern for your pleasure.}
38
+ s.test_files = [
39
+ "spec/keeper_spec.rb",
40
+ "spec/spec_helper.rb"
41
+ ]
42
+
43
+ if s.respond_to? :specification_version then
44
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
45
+ s.specification_version = 3
46
+
47
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
48
+ s.add_development_dependency(%q<rspec>, ["~> 2.1.0"])
49
+ s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
50
+ s.add_development_dependency(%q<bluecloth>, [">= 0"])
51
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
52
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
53
+ else
54
+ s.add_dependency(%q<rspec>, ["~> 2.1.0"])
55
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
56
+ s.add_dependency(%q<bluecloth>, [">= 0"])
57
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
58
+ s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
59
+ end
60
+ else
61
+ s.add_dependency(%q<rspec>, ["~> 2.1.0"])
62
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
63
+ s.add_dependency(%q<bluecloth>, [">= 0"])
64
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
65
+ s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
66
+ end
67
+ end
68
+
@@ -0,0 +1,69 @@
1
+ # coding: utf-8
2
+ require 'thread'
3
+ require 'keeper/version'
4
+
5
+ # If you are looking for the documentation you’ll most likely want {Keeper::Keeper}.
6
+ #
7
+ module Keeper
8
+ # A thread-safe blocking event pattern for your pleasure.
9
+ #
10
+ # @example
11
+ # events = Keeper::Keeper.new
12
+ #
13
+ # [:pang, :boom, :pow].each_with_index do |event, i|
14
+ # this_many = i + 1
15
+ # this_many.times do |i|
16
+ # Thread.new do
17
+ # events.wait_for(event)
18
+ # puts "#{event}:#{i}!"
19
+ # events.fire(event == :pang ? :boom : :pow)
20
+ # end
21
+ # end
22
+ # puts "#{this_many} threads waiting for #{event}"
23
+ # end
24
+ #
25
+ # print "Pause for effect"
26
+ # 3.times { sleep 1 and print "." }
27
+ # puts
28
+ #
29
+ # events.fire(:pang)
30
+ # Thread.list.reject { |th| th == Thread.current }.map(&:join)
31
+ #
32
+ class Keeper
33
+ # Create a new {Keeper::Keeper} instance.
34
+ def initialize
35
+ @waiting = {}
36
+ @mootex = Mutex.new
37
+ end
38
+
39
+ # Fires the given event, waking up the waiting threads.
40
+ #
41
+ # @param [Symbol] event
42
+ # @return [Keeper]
43
+ def fire(event)
44
+ @mootex.synchronize do
45
+ condition = @waiting.delete(event)
46
+ condition.broadcast unless condition.nil?
47
+ end
48
+ self
49
+ end
50
+
51
+ # Waits for the given event to fire.
52
+ #
53
+ # @param [Symbol] event
54
+ # @return [Keeper]
55
+ def wait_for(event)
56
+ @mootex.synchronize do
57
+ (@waiting[event] ||= ConditionVariable.new).wait(@mootex)
58
+ end
59
+ self
60
+ end
61
+
62
+ # A list of all events currently being waited for.
63
+ #
64
+ # @return [Array<Symbol>]
65
+ def waiting
66
+ @mootex.synchronize { @waiting.keys }
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,18 @@
1
+ module Keeper
2
+ # Current release version of Keeper
3
+ #
4
+ # @see http://semver.org/
5
+ module Version
6
+ # Incremented *only* on backwards **incompatible** changes.
7
+ MAJOR = 1
8
+
9
+ # Incremented *only* after adding new, backwards compatible functionality.
10
+ MINOR = 0
11
+
12
+ # Incremented *only* on backwards compatible bug fixes.
13
+ PATCH = 0
14
+
15
+ # String representation of the current version in the form X.Y.Z
16
+ STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Keeper" do
4
+ describe "#wait_for" do
5
+ context "new event" do
6
+ it "should create the event signaller"
7
+ it "should register the calling thread as waiting"
8
+ end
9
+
10
+ context "existing event" do
11
+ it "should re-use the existing signaller"
12
+ it "should not affect any other waiting threads"
13
+ it "should register the the calling thread as waiting"
14
+ end
15
+ end
16
+
17
+ describe "#fire" do
18
+ context "existing event" do
19
+ it "should release all listeners"
20
+ end
21
+
22
+ context "non-existing event" do
23
+ it "should not cause an error"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,4 @@
1
+ require 'rspec'
2
+ require 'keeper'
3
+
4
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: keeper
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ version: 1.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Kim Burgestrand
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-12-11 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 2
29
+ - 1
30
+ - 0
31
+ version: 2.1.0
32
+ type: :development
33
+ prerelease: false
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: yard
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 0
44
+ - 6
45
+ - 0
46
+ version: 0.6.0
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: bluecloth
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: bundler
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 1
72
+ - 0
73
+ - 0
74
+ version: 1.0.0
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: *id004
78
+ - !ruby/object:Gem::Dependency
79
+ name: jeweler
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ segments:
86
+ - 1
87
+ - 5
88
+ - 1
89
+ version: 1.5.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: *id005
93
+ description:
94
+ email: kim@burgestrand.se
95
+ executables: []
96
+
97
+ extensions: []
98
+
99
+ extra_rdoc_files:
100
+ - LICENSE.txt
101
+ - README.markdown
102
+ files:
103
+ - .document
104
+ - .rspec
105
+ - .yardopts
106
+ - Gemfile
107
+ - Gemfile.lock
108
+ - LICENSE.txt
109
+ - README.markdown
110
+ - Rakefile
111
+ - keeper.gemspec
112
+ - lib/keeper.rb
113
+ - lib/keeper/version.rb
114
+ - spec/keeper_spec.rb
115
+ - spec/spec_helper.rb
116
+ has_rdoc: true
117
+ homepage: http://github.com/Burgestrand/keeper
118
+ licenses:
119
+ - X11
120
+ post_install_message:
121
+ rdoc_options: []
122
+
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ hash: 2286222574126618657
131
+ segments:
132
+ - 0
133
+ version: "0"
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ none: false
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ segments:
140
+ - 0
141
+ version: "0"
142
+ requirements: []
143
+
144
+ rubyforge_project:
145
+ rubygems_version: 1.3.7
146
+ signing_key:
147
+ specification_version: 3
148
+ summary: A thread-safe blocking event pattern for your pleasure.
149
+ test_files:
150
+ - spec/keeper_spec.rb
151
+ - spec/spec_helper.rb