summaryrefslogtreecommitdiff
path: root/lib/monitor.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/monitor.rb')
-rw-r--r--lib/monitor.rb76
1 files changed, 76 insertions, 0 deletions
diff --git a/lib/monitor.rb b/lib/monitor.rb
index 721c51a9f5..5eb7bb4e03 100644
--- a/lib/monitor.rb
+++ b/lib/monitor.rb
@@ -42,6 +42,40 @@ empty_cond.signal.
=end
+
+#
+# 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.
+#
module MonitorMixin
module Accessible
protected
@@ -59,6 +93,12 @@ module MonitorMixin
end
end
+ #
+ # FIXME: This isn't documented in Nutshell.
+ #
+ # Since MonitorMixin.new_cond returns a ConditionVariable, and the example
+ # above calls while_wait and signal, this class should be documented.
+ #
class ConditionVariable
class Timeout < Exception; end
@@ -169,6 +209,9 @@ module MonitorMixin
obj.mon_initialize
end
+ #
+ # Attempts to enter exclusive section. Returns +false+ if lock fails.
+ #
def try_mon_enter
result = false
Thread.critical = true
@@ -183,6 +226,9 @@ module MonitorMixin
return result
end
+ #
+ # Enters exlusive section.
+ #
def mon_enter
Thread.critical = true
while mon_owner != nil && mon_owner != Thread.current
@@ -195,6 +241,9 @@ module MonitorMixin
Thread.critical = false
end
+ #
+ # Leaves exclusive section.
+ #
def mon_exit
if mon_owner != Thread.current
raise ThreadError, "current thread not owner"
@@ -214,6 +263,11 @@ module MonitorMixin
Thread.pass
end
+ #
+ # Enters exclusive section and executes the block. Leaves the exclusive
+ # section automatically when the block exits. See example under
+ # +MonitorMixin+.
+ #
def mon_synchronize
mon_enter
begin
@@ -224,6 +278,9 @@ module MonitorMixin
end
alias synchronize mon_synchronize
+ #
+ # FIXME: This isn't documented in Nutshell.
+ #
def new_cond
return ConditionVariable.new(self)
end
@@ -243,6 +300,25 @@ class Monitor
alias owner mon_owner
end
+
+# Documentation comments:
+# - All documentation comes from Nutshell.
+# - MonitorMixin.new_cond appears in the example, but is not documented in
+# Nutshell.
+# - All the internals (internal modules Accessible and Initializable, class
+# ConditionVariable) appear in RDoc. It might be good to hide them, by
+# making them private, or marking them :nodoc:, etc.
+# - The entire example from the RD section at the top is replicated in the RDoc
+# comment for MonitorMixin. Does the RD section need to remain?
+# - RDoc doesn't recognise aliases, so we have mon_synchronize documented, but
+# not synchronize.
+# - mon_owner is in Nutshell, but appears as an accessor in a separate module
+# here, so is hard/impossible to RDoc. Some other useful accessors
+# (mon_count and some queue stuff) are also in this module, and don't appear
+# directly in the RDoc output.
+# - in short, it may be worth changing the code layout in this file to make the
+# documentation easier
+
# Local variables:
# mode: Ruby
# tab-width: 8