normandy 0.1.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.
- checksums.yaml +7 -0
- data/lib/channel.rb +189 -0
- data/lib/channel/runtime.rb +15 -0
- data/lib/channel/timer.rb +17 -0
- data/lib/channel/waitgroup.rb +41 -0
- data/lib/normandy.rb +1 -0
- metadata +104 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dfc72d3679cf96efa105ddbb59286e2adec616f3
|
4
|
+
data.tar.gz: 9d6358833bbb0d8ae0316f21abc282c5f7e3874c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 55bd93f35b6dd626873bf18c4978975fa1c405a48f3b77619486a8344e744b611bcc8768c98228bbfc87057fea9bc2401d9b08e9d67279b48194b6fce3e48c48
|
7
|
+
data.tar.gz: c0e4a3235b16b9bed94801bf635702da18b6b2b489baca71881092ce849f8188df8a0ba451997cb7df8f2c4f57833868434183f08b11049cf88962a1e4fc0856
|
data/lib/channel.rb
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
class Channel
|
2
|
+
class Closed < StandardError; end
|
3
|
+
|
4
|
+
def initialize(size = nil)
|
5
|
+
@q = size ? SizedQueue.new(size) : Queue.new
|
6
|
+
@closed = false
|
7
|
+
@mutex = Mutex.new
|
8
|
+
@waiting = []
|
9
|
+
end
|
10
|
+
|
11
|
+
private def lock!(&block)
|
12
|
+
@mutex.synchronize(&block)
|
13
|
+
end
|
14
|
+
|
15
|
+
private def wait!
|
16
|
+
@waiting << Thread.current
|
17
|
+
@mutex.sleep
|
18
|
+
end
|
19
|
+
|
20
|
+
private def next!
|
21
|
+
loop do
|
22
|
+
thr = @waiting.shift
|
23
|
+
break if thr.nil?
|
24
|
+
next unless thr.alive?
|
25
|
+
break thr.wakeup
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private def all!
|
30
|
+
@waiting.dup.each { next! }
|
31
|
+
end
|
32
|
+
|
33
|
+
def recv
|
34
|
+
lock! do
|
35
|
+
loop do
|
36
|
+
closed! if closed? && @q.empty?
|
37
|
+
wait! && next if @q.empty?
|
38
|
+
break @q.pop
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
alias_method :pop, :recv
|
43
|
+
|
44
|
+
def send(val)
|
45
|
+
lock! do
|
46
|
+
fail Closed if closed?
|
47
|
+
@q << val
|
48
|
+
next!
|
49
|
+
end
|
50
|
+
end
|
51
|
+
alias_method :push, :send
|
52
|
+
alias_method :<<, :push
|
53
|
+
|
54
|
+
def close
|
55
|
+
lock! do
|
56
|
+
return if closed?
|
57
|
+
@closed = true
|
58
|
+
all!
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def closed?
|
63
|
+
@closed
|
64
|
+
end
|
65
|
+
|
66
|
+
private def closed!
|
67
|
+
fail Closed
|
68
|
+
end
|
69
|
+
|
70
|
+
def each
|
71
|
+
return enum_for(:each) unless block_given?
|
72
|
+
|
73
|
+
loop do
|
74
|
+
begin
|
75
|
+
e = recv
|
76
|
+
rescue Channel::Closed
|
77
|
+
return
|
78
|
+
else
|
79
|
+
yield e
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def receive_only!
|
85
|
+
ReceiveOnly.new(self)
|
86
|
+
end
|
87
|
+
alias_method :r!, :receive_only!
|
88
|
+
|
89
|
+
def send_only!
|
90
|
+
SendOnly.new(self)
|
91
|
+
end
|
92
|
+
alias_method :s!, :send_only!
|
93
|
+
|
94
|
+
class << self
|
95
|
+
def select(*channels)
|
96
|
+
selector = new
|
97
|
+
threads = channels.map do |c|
|
98
|
+
Thread.new { selector << [c.recv, c] }
|
99
|
+
end
|
100
|
+
yield selector.recv
|
101
|
+
ensure
|
102
|
+
selector.close
|
103
|
+
threads.each(&:kill).each(&:join)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class Direction < StandardError; end
|
108
|
+
class Conversion < StandardError; end
|
109
|
+
|
110
|
+
class ReceiveOnly
|
111
|
+
def initialize(channel)
|
112
|
+
@channel = channel
|
113
|
+
end
|
114
|
+
|
115
|
+
def recv
|
116
|
+
@channel.recv
|
117
|
+
end
|
118
|
+
alias_method :pop, :recv
|
119
|
+
|
120
|
+
def send(_)
|
121
|
+
fail Direction, 'receive only'
|
122
|
+
end
|
123
|
+
alias_method :push, :send
|
124
|
+
alias_method :<<, :push
|
125
|
+
|
126
|
+
def close
|
127
|
+
@channel.close
|
128
|
+
end
|
129
|
+
|
130
|
+
def closed?
|
131
|
+
@channel.closed?
|
132
|
+
end
|
133
|
+
|
134
|
+
def receive_only!
|
135
|
+
self
|
136
|
+
end
|
137
|
+
alias_method :r!, :receive_only!
|
138
|
+
|
139
|
+
def send_only!
|
140
|
+
fail Conversion, 'receive only'
|
141
|
+
end
|
142
|
+
alias_method :s!, :send_only!
|
143
|
+
|
144
|
+
def hash
|
145
|
+
@channel.hash
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class SendOnly
|
150
|
+
def initialize(channel)
|
151
|
+
@channel = channel
|
152
|
+
end
|
153
|
+
|
154
|
+
def recv
|
155
|
+
fail Direction, 'send only'
|
156
|
+
end
|
157
|
+
alias_method :pop, :recv
|
158
|
+
|
159
|
+
def send(val)
|
160
|
+
@channel.send(val)
|
161
|
+
end
|
162
|
+
alias_method :push, :send
|
163
|
+
alias_method :<<, :push
|
164
|
+
|
165
|
+
def close
|
166
|
+
@channel.close
|
167
|
+
end
|
168
|
+
|
169
|
+
def closed?
|
170
|
+
@channel.closed?
|
171
|
+
end
|
172
|
+
|
173
|
+
def receive_only!
|
174
|
+
fail Conversion, 'send only'
|
175
|
+
end
|
176
|
+
alias_method :r!, :receive_only!
|
177
|
+
|
178
|
+
def send_only!
|
179
|
+
self
|
180
|
+
end
|
181
|
+
alias_method :s!, :send_only!
|
182
|
+
|
183
|
+
def hash
|
184
|
+
@channel.hash
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
require 'channel/runtime'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Channel::Timer
|
2
|
+
attr_reader :channel
|
3
|
+
|
4
|
+
def initialize(delay)
|
5
|
+
@channel = Channel.new(1)
|
6
|
+
@prc = -> { sleep delay; channel << Time.now }
|
7
|
+
start
|
8
|
+
end
|
9
|
+
|
10
|
+
def start
|
11
|
+
Channel::Runtime.go @prc
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.after(delay)
|
15
|
+
new(delay).channel
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class WaitGroup
|
2
|
+
def initialize
|
3
|
+
@mutex = Mutex.new
|
4
|
+
@count = 0
|
5
|
+
@waiting = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def add(delta)
|
9
|
+
sync! do
|
10
|
+
@count += delta
|
11
|
+
fail 'negative WaitGroup counter' if @count < 0
|
12
|
+
if @waiting.any? && delta > 0 && @count == delta
|
13
|
+
fail 'misuse: add called concurrently with wait'
|
14
|
+
end
|
15
|
+
wake!
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def done
|
20
|
+
add(-1)
|
21
|
+
end
|
22
|
+
|
23
|
+
private def done?
|
24
|
+
@count == 0
|
25
|
+
end
|
26
|
+
|
27
|
+
def wait
|
28
|
+
sync! do
|
29
|
+
@waiting << Thread.current
|
30
|
+
@mutex.sleep until done?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private def wake!
|
35
|
+
@waiting.each { |t| t.wakeup if t.alive? }
|
36
|
+
end
|
37
|
+
|
38
|
+
private def sync!(&block)
|
39
|
+
@mutex.synchronize(&block)
|
40
|
+
end
|
41
|
+
end
|
data/lib/normandy.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'channel'
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: normandy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Loic Nageleisen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-02-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pry
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rubocop
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: test-unit
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Share memory by communicating
|
70
|
+
email: loic.nageleisen@gmail.com
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files: []
|
74
|
+
files:
|
75
|
+
- lib/channel.rb
|
76
|
+
- lib/channel/runtime.rb
|
77
|
+
- lib/channel/timer.rb
|
78
|
+
- lib/channel/waitgroup.rb
|
79
|
+
- lib/normandy.rb
|
80
|
+
homepage: https://github.com/lloeki/normandy
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
metadata: {}
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 2.5.1
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: Channels, CSP style
|
104
|
+
test_files: []
|