Do not trust locally cached mq_flags
[ruby_posix_mq.git] / lib / posix_mq.rb
blob72d6ebc00dc41a792e77e782447ce951422e37be
1 # -*- encoding: binary -*-
3 # This class represents an POSIX message queue descriptor (mqd_t)
4 # object.  It matches the C API for POSIX messages queues closely.
6 # See the link:README for examples on how to use it.
7 class POSIX_MQ
9   # version of POSIX_MQ, currently 0.7.0
10   # This constant is deprecated and will be removed in the next
11   # release.  Use +respond_to?+ instead to test for features.
12   VERSION = "0.7.0"
14   # An analogous Struct to "struct mq_attr" in C.
15   # This may be used in arguments for POSIX_MQ.new and
16   # POSIX_MQ#attr=.  POSIX_MQ#attr returns an instance
17   # of this class.
18   #
19   # See the mq_getattr(3) manpage for more information on the values.
20   Attr = Struct.new(:flags, :maxmsg, :msgsize, :curmsgs)
22   # Opens a POSIX message queue and performs operations on the
23   # given block, closing the message queue at exit.
24   # All all arguments are passed to POSIX_MQ.new.
25   def self.open(*args)
26     mq = new(*args)
27     block_given? or return mq
28     begin
29       yield mq
30     ensure
31       mq.close unless mq.closed?
32     end
33   end
35   # Executes the given block upon reception of the next message in an
36   # empty queue.  If the message queue is not empty, then this block
37   # will only be fired after the queue is emptied and repopulated with
38   # one message.
39   #
40   # This block will only be executed upon the arrival of the
41   # first message and must be reset/reenabled for subsequent
42   # notifications.  This block will execute in a separate Ruby
43   # Thread (and thus will safely have the GVL by default).
44   #
45   # This method is only supported on platforms that implement
46   # SIGEV_THREAD functionality in mq_notify(3).  So far we only
47   # know of glibc + Linux supporting this.  Please let us
48   # know if your platform can support this functionality and
49   # are willing to test for us <ruby.posix.mq@librelist.com>
50   #
51   # As far as we can tell, this method is not very useful
52   # nor efficient.  You would be better served using signals or
53   # just blocking.  On Linux and FreeBSD, you can use POSIX_MQ
54   # with I/O multiplexing (IO.select, EventMachine), too.
55   def notify(&block)
56     block.arity == 1 or
57       raise ArgumentError, "arity of notify block must be 1"
58     r, w = IO.pipe
59     self.notify_exec(w, Thread.new(r, w, self) do |r, w, mq|
60       begin
61         begin
62           r.read(1) or raise Errno::EINTR
63         rescue Errno::EINTR, Errno::EAGAIN
64           retry
65         end
66         block.call(mq)
67       ensure
68         mq.notify_cleanup
69         r.close rescue nil
70         w.close rescue nil
71       end
72     end)
73     nil
74   end if RUBY_PLATFORM =~ /linux/
76   # There's no point in ever duping a POSIX_MQ object.
77   # All send/receive operations are atomic and only one
78   # native thread may be notified at a time
79   def dup
80     self
81   end
83   # There's no point in ever cloning a POSIX_MQ object.
84   # All send/receive operations are atomic and only one
85   # native thread may be notified at a time
86   alias clone dup
88 end
90 require 'posix_mq_ext'