fiber-mon 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/fiber-mon.rb +252 -0
  2. 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
+