pmahoney/process_shared

View on GitHub
lib/mach/semaphore.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'mach/functions'
require 'mach/port'
require 'mach/host'
require 'mach/clock'

module Mach
  class Semaphore < Port
    include Functions

    # Create a new 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(opts = {})
      value = opts[:value] || 1
      task = (opts[:task] && opts[:task].to_i) || ipc_space || mach_task_self
      sync_policy = opts[:sync_policy] || :fifo

      port = if opts[:port]
               opts[:port].to_i
             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.
    #
    # @param [Hash] opts
    #
    # @option opts [Integer] :task the Mach task that owns the
    # semaphore (defaults to the owning task)
    def destroy(opts = {})
      task = opts[:task] || ipc_space || mach_task_self
      semaphore_destroy(task.to_i, port)
    end

    def signal
      semaphore_signal(port)
    end

    def signal_all
      semaphore_signal_all(port)
    end

    def wait
      semaphore_wait(port)
    end

    # @see http://pkaudio.blogspot.com/2010/05/mac-os-x-no-timed-semaphore-waits.html
    def timedwait(secs)
      timespec = TimeSpec.new
      timespec.add_seconds!(secs)

      semaphore_timedwait(port, timespec)
    end
  end
end