fiber-mon 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.
- data/fiber-mon.rb +252 -0
- metadata +69 -0
data/fiber-mon.rb
ADDED
@@ -0,0 +1,252 @@
|
|
1
|
+
#
|
2
|
+
# fiber-mon.rb -
|
3
|
+
# Copyright (C) 2010 Keiju ISHITSUKA
|
4
|
+
# (Penta Advanced Labrabries, Co.,Ltd)
|
5
|
+
#
|
6
|
+
|
7
|
+
require "forwardable"
|
8
|
+
require "monitor"
|
9
|
+
|
10
|
+
class FiberMon
|
11
|
+
include MonitorMixin
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
super
|
15
|
+
|
16
|
+
# @mon_mx = Mutex.new
|
17
|
+
# @owner = nil
|
18
|
+
# @mon_mxmx = Mutex.new
|
19
|
+
|
20
|
+
@started = false
|
21
|
+
|
22
|
+
@current = nil
|
23
|
+
|
24
|
+
@entries = []
|
25
|
+
|
26
|
+
@wait_resume = []
|
27
|
+
@wait_resume_mx = ::Mutex.new
|
28
|
+
@wait_resume_cv = ::ConditionVariable.new
|
29
|
+
|
30
|
+
mon_start
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_reader :current
|
34
|
+
|
35
|
+
def mon_start
|
36
|
+
return if @started
|
37
|
+
@started = true
|
38
|
+
th = Thread.start{
|
39
|
+
loop do
|
40
|
+
@wait_resume_mx.synchronize do
|
41
|
+
while @wait_resume.empty? && @entries.empty?
|
42
|
+
@wait_resume_cv.wait(@wait_resume_mx)
|
43
|
+
end
|
44
|
+
|
45
|
+
if block = @entries.shift
|
46
|
+
@current = Fiber.new{block.call(self)}
|
47
|
+
else
|
48
|
+
@current = @wait_resume.shift
|
49
|
+
end
|
50
|
+
end
|
51
|
+
begin
|
52
|
+
mx = @current.resume if @current
|
53
|
+
# rescue
|
54
|
+
# if $DEBUG
|
55
|
+
# p $!
|
56
|
+
# puts $@
|
57
|
+
# end
|
58
|
+
# raise
|
59
|
+
ensure
|
60
|
+
if mx.kind_of?(Mutex)
|
61
|
+
mx.unlock
|
62
|
+
end
|
63
|
+
@current = nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
}
|
67
|
+
th
|
68
|
+
end
|
69
|
+
alias start mon_start
|
70
|
+
|
71
|
+
def entry_fiber(p0 = nil, &block)
|
72
|
+
p0 = block if block
|
73
|
+
@wait_resume_mx.synchronize do
|
74
|
+
@entries.push p0
|
75
|
+
@wait_resume_cv.signal
|
76
|
+
end
|
77
|
+
end
|
78
|
+
alias entry entry_fiber
|
79
|
+
# alias start entry_fiber
|
80
|
+
|
81
|
+
def yield
|
82
|
+
@wait_resume_mx.synchronize do
|
83
|
+
@wait_resume.push @current
|
84
|
+
@wait_resume_cv.signal
|
85
|
+
end
|
86
|
+
fiber_yield
|
87
|
+
end
|
88
|
+
|
89
|
+
# def synchronize(&block)
|
90
|
+
# @mon_mxmx.synchronize do
|
91
|
+
# @mon_mx.lock
|
92
|
+
# @owner = Thread.current
|
93
|
+
# end
|
94
|
+
# begin
|
95
|
+
# block.call
|
96
|
+
# ensure
|
97
|
+
# @mon_mxmx.synchronize do
|
98
|
+
# @owner = nil
|
99
|
+
# @mon_mx.unlock
|
100
|
+
# end
|
101
|
+
# end
|
102
|
+
# end
|
103
|
+
|
104
|
+
# def fiber_yield
|
105
|
+
# begin
|
106
|
+
# status = nil
|
107
|
+
# @mon_mxmx.synchronize do
|
108
|
+
# if status = @owner == Thread.current && @mon_mx.locked?
|
109
|
+
# @mon_mx.unlock
|
110
|
+
# @owner = nil
|
111
|
+
# end
|
112
|
+
# end
|
113
|
+
# Fiber.yield
|
114
|
+
# rescue
|
115
|
+
# Log::debug_exception(self)
|
116
|
+
# ensure
|
117
|
+
# @mon_mxmx.synchronize do
|
118
|
+
# if status
|
119
|
+
# @owner = Thread.current
|
120
|
+
# @mon_mx.lock
|
121
|
+
# end
|
122
|
+
# end
|
123
|
+
# end
|
124
|
+
# end
|
125
|
+
|
126
|
+
def fiber_yield
|
127
|
+
begin
|
128
|
+
mon_check_owner
|
129
|
+
rescue
|
130
|
+
return Fiber.yield
|
131
|
+
end
|
132
|
+
if (count = mon_exit_for_cond) > 0
|
133
|
+
begin
|
134
|
+
Fiber.yield @mon_mutex
|
135
|
+
ensure
|
136
|
+
@mon_mutex.lock
|
137
|
+
end
|
138
|
+
else
|
139
|
+
Fiber.yield
|
140
|
+
end
|
141
|
+
mon_enter_for_cond(count)
|
142
|
+
end
|
143
|
+
|
144
|
+
def new_mon
|
145
|
+
Monitor.new(self)
|
146
|
+
end
|
147
|
+
|
148
|
+
def new_cv
|
149
|
+
ConditionVariable.new(self)
|
150
|
+
end
|
151
|
+
alias new_cond new_cv
|
152
|
+
|
153
|
+
def entry_wait_resume(*fbs)
|
154
|
+
@wait_resume_mx.synchronize do
|
155
|
+
@wait_resume.concat(fbs)
|
156
|
+
@wait_resume_cv.signal
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
class Monitor<::Monitor
|
161
|
+
extend Forwardable
|
162
|
+
|
163
|
+
def initialize(fibmon)
|
164
|
+
super()
|
165
|
+
@fibmon = fibmon
|
166
|
+
end
|
167
|
+
|
168
|
+
def_delegator :@fibmon, :entry_wait_resume
|
169
|
+
def_delegator :@fibmon, :current
|
170
|
+
|
171
|
+
def new_cv
|
172
|
+
ConditionVariable.new(self)
|
173
|
+
end
|
174
|
+
|
175
|
+
def fiber_yield
|
176
|
+
begin
|
177
|
+
mon_check_owner
|
178
|
+
rescue
|
179
|
+
return Fiber.yield
|
180
|
+
end
|
181
|
+
if (count = mon_exit_for_cond) > 0
|
182
|
+
begin
|
183
|
+
Fiber.yield @mon_mutex
|
184
|
+
ensure
|
185
|
+
@mon_mutex.lock
|
186
|
+
end
|
187
|
+
else
|
188
|
+
Fiber.yield
|
189
|
+
end
|
190
|
+
mon_enter_for_cond(count)
|
191
|
+
end
|
192
|
+
|
193
|
+
alias yield fiber_yield
|
194
|
+
end
|
195
|
+
|
196
|
+
class ConditionVariable
|
197
|
+
def initialize(monitor)
|
198
|
+
@mon = monitor
|
199
|
+
|
200
|
+
@waitings = []
|
201
|
+
@waitings_mx = Mutex.new
|
202
|
+
end
|
203
|
+
|
204
|
+
def synchronize(&block)
|
205
|
+
@waitings_mx.synchronize(&block)
|
206
|
+
end
|
207
|
+
|
208
|
+
def signal(&block)
|
209
|
+
@waitings_mx.synchronize do
|
210
|
+
if block_given?
|
211
|
+
yield
|
212
|
+
end
|
213
|
+
|
214
|
+
if fb = @waitings.shift
|
215
|
+
@mon.entry_wait_resume(fb)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def broadcast(&block)
|
221
|
+
@waitings_mx.synchronize do
|
222
|
+
if block_given?
|
223
|
+
yield
|
224
|
+
end
|
225
|
+
|
226
|
+
return if @waitings.empty?
|
227
|
+
fbs, @waitings = @waitings, []
|
228
|
+
@mon.entry_wait_resume(*fbs)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def wait
|
233
|
+
@waitings_mx.synchronize do
|
234
|
+
@waitings.push @mon.current
|
235
|
+
end
|
236
|
+
@mon.fiber_yield
|
237
|
+
end
|
238
|
+
|
239
|
+
def wait_until(&cond)
|
240
|
+
until cond.call
|
241
|
+
wait
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def wait_while(&cond)
|
246
|
+
while cond.call
|
247
|
+
wait
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fiber-mon
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Keiju.Ishitsuka
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-10-28 00:00:00 +09:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: |
|
23
|
+
Simple fiber scheduler for Ruby.
|
24
|
+
|
25
|
+
email: keiju@ishitsuka.com
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files: []
|
31
|
+
|
32
|
+
files:
|
33
|
+
- fiber-mon.rb
|
34
|
+
has_rdoc: true
|
35
|
+
homepage: http://github.com/keiju/fiber-mon
|
36
|
+
licenses: []
|
37
|
+
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
|
41
|
+
require_paths:
|
42
|
+
- .
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
hash: 3
|
49
|
+
segments:
|
50
|
+
- 0
|
51
|
+
version: "0"
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
requirements: []
|
62
|
+
|
63
|
+
rubyforge_project: fiber-mon
|
64
|
+
rubygems_version: 1.3.7
|
65
|
+
signing_key:
|
66
|
+
specification_version: 3
|
67
|
+
summary: Simple fiber scheduler for Ruby
|
68
|
+
test_files: []
|
69
|
+
|