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.
- data/.document +5 -0
- data/.rspec +5 -0
- data/.yardopts +3 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +30 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +45 -0
- data/Rakefile +31 -0
- data/keeper.gemspec +68 -0
- data/lib/keeper.rb +69 -0
- data/lib/keeper/version.rb +18 -0
- data/spec/keeper_spec.rb +26 -0
- data/spec/spec_helper.rb +4 -0
- metadata +151 -0
data/.document
ADDED
data/.rspec
ADDED
data/.yardopts
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -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)
|
data/LICENSE.txt
ADDED
@@ -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.
|
data/README.markdown
ADDED
@@ -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.
|
data/Rakefile
ADDED
@@ -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
|
data/keeper.gemspec
ADDED
@@ -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
|
+
|
data/lib/keeper.rb
ADDED
@@ -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
|
data/spec/keeper_spec.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
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
|