Expand documentation; fix markup.
This commit is contained in:
parent
27e8aeb4c4
commit
d102786090
|
@ -8,17 +8,28 @@ module ProcessShared
|
|||
include ProcessShared::PSem
|
||||
public
|
||||
|
||||
# Generate a name for a semaphore.
|
||||
# Generate a name for a semaphore. If +name+ is given, it is used
|
||||
# as the name (and so a semaphore could be shared by arbitrary
|
||||
# processes not forked from one another). Otherwise, a name is
|
||||
# generated containing +middle+ and the process id.
|
||||
#
|
||||
# @param [String] middle arbitrary string used in the middle
|
||||
# @param [String] name if given, used as the name
|
||||
# @return [String] name, or the generated name
|
||||
def self.gen_name(middle, name = nil)
|
||||
if name
|
||||
name
|
||||
else
|
||||
@count ||= 0
|
||||
@count += 1
|
||||
"ps-#{middle}-#{Process.pid}-#{@count}"
|
||||
"ps-#{middle}-#{::Process.pid}-#{@count}"
|
||||
end
|
||||
end
|
||||
|
||||
# Make a Proc suitable for use as a finalizer that will call
|
||||
# +psem_unlink+ on +name+ and ignore system errors.
|
||||
#
|
||||
# @return [Proc] a finalizer
|
||||
def self.make_finalizer(name)
|
||||
proc { ProcessShared::PSem.psem_unlink(name, nil) }
|
||||
end
|
||||
|
|
|
@ -2,12 +2,15 @@ require 'process_shared/psem'
|
|||
require 'process_shared/semaphore'
|
||||
|
||||
module ProcessShared
|
||||
# BoundedSemaphore is identical to Semaphore except that its value
|
||||
# is not permitted to rise above a maximum. When the value is at
|
||||
# the maximum, calls to #post will have no effect.
|
||||
class BoundedSemaphore < Semaphore
|
||||
# With no associated block, open is a synonym for
|
||||
# Semaphore.new. If the optional code block is given, it will be
|
||||
# passed `sem` as an argument, and the Semaphore object will
|
||||
# passed +sem+ as an argument, and the Semaphore object will
|
||||
# automatically be closed when the block terminates. In this
|
||||
# instance, Semaphore.open returns the value of the block.
|
||||
# instance, BoundedSemaphore.open returns the value of the block.
|
||||
#
|
||||
# @param [Integer] value the initial semaphore value
|
||||
# @param [String] name not currently supported
|
||||
|
@ -15,9 +18,9 @@ module ProcessShared
|
|||
new(maxvalue, value, name).with_self(&block)
|
||||
end
|
||||
|
||||
# Create a new semaphore with initial value `value`. After
|
||||
# Kernel#fork, the semaphore will be shared across two (or more)
|
||||
# processes. The semaphore must be closed with #close in each
|
||||
# Create a new semaphore with initial value +value+. After
|
||||
# {Kernel#fork}, the semaphore will be shared across two (or more)
|
||||
# processes. The semaphore must be closed with {#close} in each
|
||||
# process that no longer needs the semaphore.
|
||||
#
|
||||
# (An object finalizer is registered that will close the semaphore
|
||||
|
|
|
@ -4,12 +4,27 @@ require 'process_shared/shared_memory'
|
|||
require 'process_shared/process_error'
|
||||
|
||||
module ProcessShared
|
||||
# This Mutex class is implemented as a BoundedSemaphore with a
|
||||
# maximum value of 1. Additionally, the locking process is tracked,
|
||||
# and {ProcessError} is raised if either {#unlock} is called by a
|
||||
# process different from the locking process, or if {#lock} is
|
||||
# called while the process already holds the lock (i.e. the mutex is
|
||||
# not re-entrant). This tracking is not without performance cost,
|
||||
# of course (current implementation uses an additional
|
||||
# {BoundedSemaphore} and {SharedMemory} segment).
|
||||
#
|
||||
# The API is intended to be identical to the {::Mutex} in the core
|
||||
# Ruby library.
|
||||
#
|
||||
# TODO: the core Ruby api has no #close method, but this Mutex must
|
||||
# release its {BoundedSemaphore} and {SharedMemory} resources. For
|
||||
# now, rely on the object finalizers of those objects...
|
||||
class Mutex
|
||||
include WithSelf
|
||||
# include WithSelf
|
||||
|
||||
def self.open(&block)
|
||||
new.with_self(&block)
|
||||
end
|
||||
# def self.open(&block)
|
||||
# new.with_self(&block)
|
||||
# end
|
||||
|
||||
def initialize
|
||||
@internal_sem = BoundedSemaphore.new(1)
|
||||
|
@ -73,6 +88,8 @@ module ProcessShared
|
|||
|
||||
# Acquire the lock, yield the block, then ensure the lock is
|
||||
# unlocked.
|
||||
#
|
||||
# @return [Object] the result of the block
|
||||
def synchronize
|
||||
lock
|
||||
begin
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
module ProcessShared
|
||||
module PosixCall
|
||||
# Replace methods in `syms` with error checking wrappers that
|
||||
# invoke the original method and raise a SystemCallError with the
|
||||
# current errno if the return value is an error.
|
||||
# Replace methods in +syms+ with error checking wrappers that
|
||||
# invoke the original method and raise a {SystemCallError} with
|
||||
# the current errno if the return value is an error.
|
||||
#
|
||||
# Errors are detected if the block returns true when called with
|
||||
# the original method's return value.
|
||||
|
|
|
@ -5,7 +5,7 @@ module ProcessShared
|
|||
class Semaphore < AbstractSemaphore
|
||||
# With no associated block, open is a synonym for
|
||||
# Semaphore.new. If the optional code block is given, it will be
|
||||
# passed `sem` as an argument, and the Semaphore object will
|
||||
# passed +sem+ as an argument, and the Semaphore object will
|
||||
# automatically be closed when the block terminates. In this
|
||||
# instance, Semaphore.open returns the value of the block.
|
||||
#
|
||||
|
@ -15,7 +15,7 @@ module ProcessShared
|
|||
new(value, name).with_self(&block)
|
||||
end
|
||||
|
||||
# Create a new semaphore with initial value `value`. After
|
||||
# Create a new semaphore with initial value +value+. After
|
||||
# Kernel#fork, the semaphore will be shared across two (or more)
|
||||
# processes. The semaphore must be closed with #close in each
|
||||
# process that no longer needs the semaphore.
|
||||
|
@ -33,7 +33,7 @@ module ProcessShared
|
|||
end
|
||||
|
||||
# Decrement the value of the semaphore. If the value is zero,
|
||||
# wait until another process increments via #post.
|
||||
# wait until another process increments via {#post}.
|
||||
def wait
|
||||
psem_wait(sem, err)
|
||||
end
|
||||
|
@ -44,7 +44,8 @@ module ProcessShared
|
|||
psem_post(sem, err)
|
||||
end
|
||||
|
||||
# Get the current value of the semaphore.
|
||||
# Get the current value of the semaphore. Raises {Errno::NOTSUP} on
|
||||
# platforms that don't support this (e.g. Mac OS X).
|
||||
#
|
||||
# @return [Integer] the current value of the semaphore.
|
||||
def value
|
||||
|
@ -53,6 +54,11 @@ module ProcessShared
|
|||
int.get_int(0)
|
||||
end
|
||||
|
||||
# Release the resources associated with this semaphore. Calls to
|
||||
# other methods are undefined after {#close} has been called.
|
||||
#
|
||||
# Close must be called when the semaphore is no longer needed. An
|
||||
# object finalizer will close the semaphore as a last resort.
|
||||
def close
|
||||
psem_close(sem, err)
|
||||
end
|
||||
|
|
|
@ -2,8 +2,8 @@ module ProcessShared
|
|||
module WithSelf
|
||||
# With no associated block, return self. If the optional code
|
||||
# block is given, it will be passed `self` as an argument, and the
|
||||
# self object will automatically be closed (by invoking `close` on
|
||||
# `self`) when the block terminates. In this instance, value of
|
||||
# self object will automatically be closed (by invoking +close+ on
|
||||
# +self+) when the block terminates. In this instance, value of
|
||||
# the block is returned.
|
||||
def with_self
|
||||
if block_given?
|
||||
|
|
Loading…
Reference in New Issue