Move with_self open-with-block helper to common module from posix semaphore implementation.

This commit is contained in:
Patrick Mahoney 2012-02-01 19:44:24 -06:00
parent 63d10c12a2
commit 71aa552213
2 changed files with 30 additions and 87 deletions

View File

@ -1,8 +1,9 @@
require 'process_shared/semaphore'
require 'process_shared/posix/errno'
require 'process_shared/posix/libc'
require 'process_shared/posix/time_val'
require 'process_shared/posix/time_spec'
require 'process_shared/with_self'
module ProcessShared
module Posix
@ -34,7 +35,7 @@ module ProcessShared
end
include Foreign
include ProcessShared::WithSelf
include ProcessShared::Semaphore
# Make a Proc suitable for use as a finalizer that will call
# +shm_unlink+ on +sem+.
@ -44,17 +45,6 @@ module ProcessShared
proc { LibC.shm_unlink(sem) }
end
# 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
# automatically be closed when the block terminates. In this
# instance, Semaphore.open returns the value of the block.
#
# @param [Integer] value the initial semaphore value
def self.open(value = 1, &block)
new(value).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

View File

@ -1,8 +1,18 @@
require 'process_shared/psem'
require 'process_shared/abstract_semaphore'
require 'process_shared/with_self'
module ProcessShared
class Semaphore < AbstractSemaphore
module Semaphore
include ProcessShared::WithSelf
class << self
# the implementation to use to create semaphores. impl is set
# based on the platform in 'process_shared'
attr_accessor :impl
def new(*args)
impl.new(*args)
end
# 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
@ -10,75 +20,18 @@ module ProcessShared
# instance, Semaphore.open returns the value of the block.
#
# @param [Integer] value the initial semaphore value
# @param [String] name not currently supported
def self.open(value = 1, name = nil, &block)
new(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
# process that no longer needs the semaphore.
#
# (An object finalizer is registered that will close the semaphore
# to avoid memory leaks, but this should be considered a last
# resort).
#
# @param [Integer] value the initial semaphore value
# @param [String] name not currently supported
def initialize(value = 1, name = nil)
init(PSem.sizeof_psem_t, 'psem', name) do |sem_name|
psem_open(sem, sem_name, value, err)
def open(value = 1, &block)
new(value).with_self(&block)
end
end
# Decrement the value of the semaphore. If the value is zero,
# wait until another process increments via {#post}.
def wait
psem_wait(sem, err)
def synchronize
wait
begin
yield
ensure
post
end
# Decrement the value of the semaphore if it can be done
# immediately (i.e. if it was non-zero). Otherwise, wait up to
# +timeout+ seconds until another process increments via {#post}.
#
# @param timeout [Numeric] the maximum seconds to wait, or nil to not wait
#
# @return If +timeout+ is nil and the semaphore cannot be
# decremented immediately, raise Errno::EAGAIN. If +timeout+
# passed before the semaphore could be decremented, raise
# Errno::ETIMEDOUT.
def try_wait(timeout = nil)
if timeout
psem_timedwait(sem, timeout, err)
else
psem_trywait(sem, err)
end
end
# Increment the value of the semaphore. If other processes are
# waiting on this semaphore, one will be woken.
def post
psem_post(sem, err)
end
# 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
int = FFI::MemoryPointer.new(:int)
psem_getvalue(sem, int, err)
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
end
end