From 9f17aac114776b886cdcc5720b6fd243d4684e55 Mon Sep 17 00:00:00 2001 From: Patrick Mahoney Date: Mon, 16 Jan 2012 08:14:58 -0600 Subject: [PATCH] Modify args to Semaphore and Port constructors to accept existing ports. --- lib/mach/functions.rb | 6 ++++-- lib/mach/port.rb | 29 ++++++++++++++++++----------- lib/mach/semaphore.rb | 23 +++++++++++++++++------ lib/mach/task.rb | 7 +++++-- spec/mach/semaphore_spec.rb | 4 ++-- 5 files changed, 46 insertions(+), 23 deletions(-) diff --git a/lib/mach/functions.rb b/lib/mach/functions.rb index aae5bb0..5fb47b6 100644 --- a/lib/mach/functions.rb +++ b/lib/mach/functions.rb @@ -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) diff --git a/lib/mach/port.rb b/lib/mach/port.rb index f1cae0b..87759ae 100644 --- a/lib/mach/port.rb +++ b/lib/mach/port.rb @@ -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 diff --git a/lib/mach/semaphore.rb b/lib/mach/semaphore.rb index 5a4c937..29947d9 100644 --- a/lib/mach/semaphore.rb +++ b/lib/mach/semaphore.rb @@ -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. diff --git a/lib/mach/task.rb b/lib/mach/task.rb index 2710d60..6a1329f 100644 --- a/lib/mach/task.rb +++ b/lib/mach/task.rb @@ -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 diff --git a/spec/mach/semaphore_spec.rb b/spec/mach/semaphore_spec.rb index 98e1468..03d8b61 100644 --- a/spec/mach/semaphore_spec.rb +++ b/spec/mach/semaphore_spec.rb @@ -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