ruby_posix_mq.git  about / heads / tags
POSIX message queues for Ruby
blob 2dc6dcf90544342126849799d4c8326ed18d26db 2776 bytes (raw)
$ git show HEAD:lib/posix_mq.rb	# shows this blob on the CLI

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
 
# -*- frozen_string_literal: true -*-
#
# This class represents an POSIX message queue descriptor (mqd_t)
# object.  It matches the C API for POSIX messages queues closely.
#
# See the link:README for examples on how to use it.
class POSIX_MQ

  # An analogous Struct to "struct mq_attr" in C.
  # This may be used in arguments for POSIX_MQ.new and
  # POSIX_MQ#attr=.  POSIX_MQ#attr returns an instance
  # of this class.
  #
  # See the mq_getattr(3) manpage for more information on the values.
  Attr = Struct.new(:flags, :maxmsg, :msgsize, :curmsgs)

  # Opens a POSIX message queue and performs operations on the
  # given block, closing the message queue at exit.
  # All all arguments are passed to POSIX_MQ.new.
  def self.open(*args)
    mq = new(*args)
    block_given? or return mq
    begin
      yield mq
    ensure
      mq.close unless mq.closed?
    end
  end

  # Executes the given block upon reception of the next message in an
  # empty queue.  If the message queue is not empty, then this block
  # will only be fired after the queue is emptied and repopulated with
  # one message.
  #
  # This block will only be executed upon the arrival of the
  # first message and must be reset/reenabled for subsequent
  # notifications.  This block will execute in a separate Ruby
  # Thread (and thus will safely have the GVL by default).
  #
  # This method is only supported on platforms that implement
  # SIGEV_THREAD functionality in mq_notify(3).  So far we only
  # know of glibc + Linux supporting this.  Please let us
  # know if your platform can support this functionality and
  # are willing to test for us <ruby-posix-mq@bogomips.org>
  #
  # As far as we can tell, this method is not very useful
  # nor efficient.  You would be better served using signals or
  # just blocking.  On Linux and FreeBSD, you can use POSIX_MQ
  # with I/O multiplexing (IO.select, EventMachine), too.
  def notify(&block)
    block.arity == 1 or
      raise ArgumentError, "arity of notify block must be 1"
    r, w = IO.pipe
    notify_exec(w, Thread.new(block) do |blk|
      begin
        begin
          r.read(1) or raise Errno::EINTR
        rescue Errno::EINTR, Errno::EAGAIN
          retry
        end
        blk.call(self)
      ensure
        notify_cleanup
        r.close rescue nil
        w.close rescue nil
      end
    end)
    nil
  end if RUBY_PLATFORM =~ /linux/

  # There's no point in ever duping a POSIX_MQ object.
  # All send/receive operations are atomic and only one
  # native thread may be notified at a time
  def dup
    self
  end

  # There's no point in ever cloning a POSIX_MQ object.
  # All send/receive operations are atomic and only one
  # native thread may be notified at a time
  alias clone dup
end

require 'posix_mq_ext'

git clone https://yhbt.net/ruby_posix_mq.git