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.
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
+