| Module | MonitorMixin |
| In: |
lib/monitor.rb
|
Adds monitor functionality to an arbitrary object by mixing the module with include. For example:
require 'monitor.rb'
buf = []
buf.extend(MonitorMixin)
empty_cond = buf.new_cond
# consumer
Thread.start do
loop do
buf.synchronize do
empty_cond.wait_while { buf.empty? }
print buf.shift
end
end
end
# producer
while line = ARGF.gets
buf.synchronize do
buf.push(line)
empty_cond.signal
end
end
The consumer thread waits for the producer thread to push a line to buf while buf.empty?, and the producer thread (main thread) reads a line from ARGF and push it to buf, then call empty_cond.signal.
# File lib/monitor.rb, line 182
182: def self.extend_object(obj)
183: super(obj)
184: obj.instance_eval {mon_initialize()}
185: end
Enters exclusive section.
# File lib/monitor.rb, line 209
209: def mon_enter
210: Thread.critical = true
211: mon_acquire(@mon_entering_queue)
212: @mon_count += 1
213: Thread.critical = false
214: end
Leaves exclusive section.
# File lib/monitor.rb, line 219
219: def mon_exit
220: mon_check_owner
221: Thread.critical = true
222: @mon_count -= 1
223: if @mon_count == 0
224: mon_release
225: end
226: Thread.critical = false
227: Thread.pass
228: end
Enters exclusive section and executes the block. Leaves the exclusive section automatically when the block exits. See example under MonitorMixin.
# File lib/monitor.rb, line 235
235: def mon_synchronize
236: mon_enter
237: begin
238: yield
239: ensure
240: mon_exit
241: end
242: end
Attempts to enter exclusive section. Returns false if lock fails.
# File lib/monitor.rb, line 190
190: def mon_try_enter
191: result = false
192: Thread.critical = true
193: if @mon_owner.nil?
194: @mon_owner = Thread.current
195: end
196: if @mon_owner == Thread.current
197: @mon_count += 1
198: result = true
199: end
200: Thread.critical = false
201: return result
202: end
# File lib/monitor.rb, line 278
278: def mon_acquire(queue)
279: while @mon_owner && @mon_owner != Thread.current
280: queue.push(Thread.current)
281: Thread.stop
282: Thread.critical = true
283: end
284: @mon_owner = Thread.current
285: end
Throw a ThreadError exception if the current thread does‘t own the monitor
# File lib/monitor.rb, line 272
272: def mon_check_owner
273: if @mon_owner != Thread.current
274: raise ThreadError, "current thread not owner"
275: end
276: end
# File lib/monitor.rb, line 294
294: def mon_enter_for_cond(count)
295: mon_acquire(@mon_waiting_queue)
296: @mon_count = count
297: end
# File lib/monitor.rb, line 299
299: def mon_exit_for_cond
300: count = @mon_count
301: @mon_count = 0
302: mon_release
303: return count
304: end
called by initialize method to set defaults for instance variables.
# File lib/monitor.rb, line 263
263: def mon_initialize
264: @mon_owner = nil
265: @mon_count = 0
266: @mon_entering_queue = []
267: @mon_waiting_queue = []
268: end