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/errno'
require 'process_shared/posix/libc' require 'process_shared/posix/libc'
require 'process_shared/posix/time_val' require 'process_shared/posix/time_val'
require 'process_shared/posix/time_spec' require 'process_shared/posix/time_spec'
require 'process_shared/with_self'
module ProcessShared module ProcessShared
module Posix module Posix
@ -34,7 +35,7 @@ module ProcessShared
end end
include Foreign include Foreign
include ProcessShared::WithSelf include ProcessShared::Semaphore
# Make a Proc suitable for use as a finalizer that will call # Make a Proc suitable for use as a finalizer that will call
# +shm_unlink+ on +sem+. # +shm_unlink+ on +sem+.
@ -44,17 +45,6 @@ module ProcessShared
proc { LibC.shm_unlink(sem) } proc { LibC.shm_unlink(sem) }
end 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 # Create a new semaphore with initial value +value+. After
# Kernel#fork, the semaphore will be shared across two (or more) # Kernel#fork, the semaphore will be shared across two (or more)
# processes. The semaphore must be closed with #close in each # processes. The semaphore must be closed with #close in each

View File

@ -1,84 +1,37 @@
require 'process_shared/psem' require 'process_shared/with_self'
require 'process_shared/abstract_semaphore'
module ProcessShared module ProcessShared
class Semaphore < AbstractSemaphore module Semaphore
# With no associated block, open is a synonym for include ProcessShared::WithSelf
# 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
# @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 class << self
# Kernel#fork, the semaphore will be shared across two (or more) # the implementation to use to create semaphores. impl is set
# processes. The semaphore must be closed with #close in each # based on the platform in 'process_shared'
# process that no longer needs the semaphore. attr_accessor :impl
#
# (An object finalizer is registered that will close the semaphore def new(*args)
# to avoid memory leaks, but this should be considered a last impl.new(*args)
# resort). end
#
# @param [Integer] value the initial semaphore value # With no associated block, open is a synonym for
# @param [String] name not currently supported # Semaphore.new. If the optional code block is given, it will be
def initialize(value = 1, name = nil) # passed +sem+ as an argument, and the Semaphore object will
init(PSem.sizeof_psem_t, 'psem', name) do |sem_name| # automatically be closed when the block terminates. In this
psem_open(sem, sem_name, value, err) # instance, Semaphore.open returns the value of the block.
#
# @param [Integer] value the initial semaphore value
def open(value = 1, &block)
new(value).with_self(&block)
end end
end end
# Decrement the value of the semaphore. If the value is zero, def synchronize
# wait until another process increments via {#post}. wait
def wait begin
psem_wait(sem, err) yield
end ensure
post
# 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
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
end end