Modify args to Semaphore and Port constructors to accept existing ports.

This commit is contained in:
Patrick Mahoney 2012-01-16 08:14:58 -06:00
parent 14e5b893bf
commit 9f17aac114
5 changed files with 46 additions and 23 deletions

View File

@ -1,3 +1,5 @@
require 'ffi'
module Mach
# FFI wrapper around a subset of the Mach API (likely Mac OS X
# specific).
@ -212,13 +214,13 @@ module Mach
attach_mach_function(:task_get_special_port,
[:task_t,
:int,
MachSpecialPort,
:mach_port_pointer_t],
:kern_return_t)
attach_mach_function(:task_set_special_port,
[:task_t,
:int,
MachSpecialPort,
:mach_port_t],
:kern_return_t)

View File

@ -6,20 +6,27 @@ module Mach
attr_reader :ipc_space, :port
# either initialize(port, opts) -or- initialize(opts)
def initialize(opts = {}, opts2 = {})
# @param [Hash] opts
#
# @option opts [Integer] :ipc_space defaults to +mach_task_self+
#
# @option opts [MachPortRight] :right defaults to +:receive+
#
# @option opts [Port, Integer] :port if given, the existing port
# is wrapped in a new Port object; otherwise a new port is
# allocated according to the other options
def initialize(opts = {})
if opts.kind_of? Hash
ipc_space = opts[:ipc_space] || mach_task_self
@ipc_space = opts[:ipc_space] || mach_task_self
right = opts[:right] || :receive
mem = new_memory_pointer(:mach_port_right_t)
mach_port_allocate(ipc_space, right, mem)
@port = mem.get_uint(0)
@ipc_space = ipc_space
else
@port = opts
@ipc_space = opts2[:ipc_space] || mach_task_self
@port = if opts[:port]
opts[:port].kind_of?(Port) ? opts[:port].port : opts[:port]
else
mem = new_memory_pointer(:mach_port_right_t)
mach_port_allocate(@ipc_space, right, mem)
mem.get_uint(0)
end
end
end

View File

@ -7,24 +7,35 @@ module Mach
# Create a new Semaphore.
#
# @param [Integer] value the initial value of the semaphore
#
# @param [Hash] opts
#
# @option opts [Integer] :value the initial value of the
# semaphore; defaults to 1
#
# @option opts [Integer] :task the Mach task that owns the
# semaphore (defaults to Mach.task_self)
#
# @options opts [Integer] :sync_policy the sync policy for this
# semaphore (defaults to SyncPolicy::FIFO)
#
# @options opts [Integer] :port existing port to wrap with a
# Semaphore object; otherwise a new semaphore is created
#
# @return [Integer] a semaphore port name
def initialize(value = 1, opts = {})
def initialize(opts = {})
value = opts[:value] || 1
task = opts[:task] || ipc_space || mach_task_self
sync_policy = opts[:sync_policy] || :fifo
mem = new_memory_pointer(:semaphore_t)
semaphore_create(task, mem, sync_policy, value)
super(mem.get_uint(0), :ipc_space => task)
port = if opts[:port]
opts[:port]
else
mem = new_memory_pointer(:semaphore_t)
semaphore_create(task, mem, sync_policy, value)
mem.get_uint(0)
end
super(:port => port, :ipc_space => task)
end
# Destroy a Semaphore.

View File

@ -11,17 +11,20 @@ module Mach
end
def initialize(task)
super(task)
super(:port => task)
end
alias_method :task, :port
# @param [MachSpecialPort] which_port
def get_special_port(which_port)
mem = FFI::MemoryPointer.new(:int)
task_get_special_port(task, which_port, mem)
Port.new(mem.get_int(0))
Port.new(:port => mem.get_int(0))
end
# @param [MachSpecialPort] which_port
#
# @param [Port,Integer] newport
def set_special_port(which_port, newport)
p = newport.respond_to?(:port) ? newport.port : newport

View File

@ -20,12 +20,12 @@ module Mach
end
it 'raises exception with invalid args' do
p = proc { Semaphore.new(1, :sync_policy => :no_such) }
p = proc { Semaphore.new(:sync_policy => :no_such) }
p.must_raise ArgumentError # Error::INVALID_ARGUMENT
end
it 'signals/waits in same task' do
sem = Semaphore.new(0)
sem = Semaphore.new(:value => 0)
sem.signal
sem.wait
sem.destroy