Move with_self open-with-block helper to common module from posix semaphore implementation.
This commit is contained in:
parent
63d10c12a2
commit
71aa552213
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue