posix_mq 0.7.0 → 0.8.0pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.wrongdoc.yml CHANGED
@@ -4,4 +4,4 @@ cgit_url: http://bogomips.org/ruby_posix_mq.git
4
4
  git_url: git://bogomips.org/ruby_posix_mq.git
5
5
  changelog_since: 0.4.0
6
6
  merge_html:
7
- posix-mq-rb_1: Documentation/posix-mq.rb.1.html
7
+ posix-mq-rb_1: Documentation/posix-mq-rb.1.html
data/GIT-VERSION-GEN CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v0.7.0.GIT
4
+ DEF_VER=v0.8.0pre.GIT
5
5
 
6
6
  LF='
7
7
  '
@@ -62,10 +62,13 @@ static int MQ_IO_CLOSE(struct posix_mq *mq)
62
62
  }
63
63
  #endif
64
64
 
65
- static VALUE cPOSIX_MQ, cAttr;
65
+ # define PMQ_WANTARRAY (1<<0)
66
+ # define PMQ_TRY (1<<1)
67
+
68
+ static VALUE cAttr;
66
69
  static ID id_new, id_kill, id_fileno, id_mul, id_divmod;
67
70
  static ID id_flags, id_maxmsg, id_msgsize, id_curmsgs;
68
- static ID sym_r, sym_w, sym_rw;
71
+ static VALUE sym_r, sym_w, sym_rw;
69
72
  static const mqd_t MQD_INVALID = (mqd_t)-1;
70
73
 
71
74
  /* Ruby 1.8.6+ macros (for compatibility with Ruby 1.9) */
@@ -438,7 +441,11 @@ static VALUE init(int argc, VALUE *argv, VALUE self)
438
441
 
439
442
  mq->des = (mqd_t)xopen(&x);
440
443
  if (mq->des == MQD_INVALID) {
441
- if (errno == ENOMEM || errno == EMFILE || errno == ENFILE) {
444
+ switch (errno) {
445
+ case ENOMEM:
446
+ case EMFILE:
447
+ case ENFILE:
448
+ case ENOSPC:
442
449
  rb_gc();
443
450
  mq->des = (mqd_t)xopen(&x);
444
451
  }
@@ -501,6 +508,7 @@ static void setup_send_buffer(struct rw_args *x, VALUE buffer)
501
508
  x->msg_len = (size_t)RSTRING_LEN(buffer);
502
509
  }
503
510
 
511
+ static VALUE _send(int sflags, int argc, VALUE *argv, VALUE self);
504
512
  /*
505
513
  * call-seq:
506
514
  * mq.send(string [,priority[, timeout]]) => nil
@@ -514,7 +522,12 @@ static void setup_send_buffer(struct rw_args *x, VALUE buffer)
514
522
  * On some older systems, the +timeout+ argument is not currently
515
523
  * supported and may raise NotImplementedError if +timeout+ is used.
516
524
  */
517
- static VALUE _send(int argc, VALUE *argv, VALUE self)
525
+ static VALUE my_send(int argc, VALUE *argv, VALUE self)
526
+ {
527
+ _send(0, argc, argv, self);
528
+ }
529
+
530
+ static VALUE _send(int sflags, int argc, VALUE *argv, VALUE self)
518
531
  {
519
532
  struct posix_mq *mq = get(self, 1);
520
533
  struct rw_args x;
@@ -529,15 +542,14 @@ static VALUE _send(int argc, VALUE *argv, VALUE self)
529
542
  x.timeout = convert_timeout(&expire, timeout);
530
543
  x.msg_prio = NIL_P(prio) ? 0 : NUM2UINT(prio);
531
544
 
532
- if (mq->attr.mq_flags & O_NONBLOCK)
533
- rv = (mqd_t)xsend(&x);
534
- else
535
- rv = (mqd_t)rb_thread_blocking_region(xsend, &x,
536
- RUBY_UBF_IO, 0);
537
- if (rv == MQD_INVALID)
545
+ rv = (mqd_t)rb_thread_blocking_region(xsend, &x, RUBY_UBF_IO, 0);
546
+ if (rv == MQD_INVALID) {
547
+ if (errno == EAGAIN && (sflags & PMQ_TRY))
548
+ return Qfalse;
538
549
  rb_sys_fail("mq_send");
550
+ }
539
551
 
540
- return Qnil;
552
+ return (sflags & PMQ_TRY) ? Qtrue : Qnil;
541
553
  }
542
554
 
543
555
  /*
@@ -558,12 +570,7 @@ static VALUE send0(VALUE self, VALUE buffer)
558
570
  x.timeout = NULL;
559
571
  x.msg_prio = 0;
560
572
 
561
- if (mq->attr.mq_flags & O_NONBLOCK)
562
- rv = (mqd_t)xsend(&x);
563
- else
564
- rv = (mqd_t)rb_thread_blocking_region(xsend, &x,
565
- RUBY_UBF_IO, 0);
566
-
573
+ rv = (mqd_t)rb_thread_blocking_region(xsend, &x, RUBY_UBF_IO, 0);
567
574
  if (rv == MQD_INVALID)
568
575
  rb_sys_fail("mq_send");
569
576
 
@@ -590,7 +597,7 @@ static VALUE to_io(VALUE self)
590
597
  }
591
598
  #endif
592
599
 
593
- static VALUE _receive(int wantarray, int argc, VALUE *argv, VALUE self);
600
+ static VALUE _receive(int rflags, int argc, VALUE *argv, VALUE self);
594
601
 
595
602
  /*
596
603
  * call-seq:
@@ -613,7 +620,7 @@ static VALUE _receive(int wantarray, int argc, VALUE *argv, VALUE self);
613
620
  */
614
621
  static VALUE receive(int argc, VALUE *argv, VALUE self)
615
622
  {
616
- return _receive(1, argc, argv, self);
623
+ return _receive(PMQ_WANTARRAY, argc, argv, self);
617
624
  }
618
625
 
619
626
  /*
@@ -639,7 +646,7 @@ static VALUE shift(int argc, VALUE *argv, VALUE self)
639
646
  return _receive(0, argc, argv, self);
640
647
  }
641
648
 
642
- static VALUE _receive(int wantarray, int argc, VALUE *argv, VALUE self)
649
+ static VALUE _receive(int rflags, int argc, VALUE *argv, VALUE self)
643
650
  {
644
651
  struct posix_mq *mq = get(self, 1);
645
652
  struct rw_args x;
@@ -667,18 +674,16 @@ static VALUE _receive(int wantarray, int argc, VALUE *argv, VALUE self)
667
674
  x.msg_len = (size_t)mq->attr.mq_msgsize;
668
675
  x.des = mq->des;
669
676
 
670
- if (mq->attr.mq_flags & O_NONBLOCK) {
671
- r = (ssize_t)xrecv(&x);
672
- } else {
673
- r = (ssize_t)rb_thread_blocking_region(xrecv, &x,
674
- RUBY_UBF_IO, 0);
675
- }
676
- if (r < 0)
677
+ r = (ssize_t)rb_thread_blocking_region(xrecv, &x, RUBY_UBF_IO, 0);
678
+ if (r < 0) {
679
+ if (errno == EAGAIN && (rflags & PMQ_TRY))
680
+ return Qnil;
677
681
  rb_sys_fail("mq_receive");
682
+ }
678
683
 
679
684
  rb_str_set_len(buffer, r);
680
685
 
681
- if (wantarray)
686
+ if (rflags & PMQ_WANTARRAY)
682
687
  return rb_ary_new3(2, buffer, UINT2NUM(x.msg_prio));
683
688
  return buffer;
684
689
  }
@@ -940,10 +945,12 @@ static VALUE setnotify(VALUE self, VALUE arg)
940
945
  *
941
946
  * Returns the current non-blocking state of the message queue descriptor.
942
947
  */
943
- static VALUE getnonblock(VALUE self)
948
+ static VALUE nonblock_p(VALUE self)
944
949
  {
945
950
  struct posix_mq *mq = get(self, 1);
946
951
 
952
+ if (mq_getattr(mq->des, &mq->attr) < 0)
953
+ rb_sys_fail("mq_getattr");
947
954
  return mq->attr.mq_flags & O_NONBLOCK ? Qtrue : Qfalse;
948
955
  }
949
956
 
@@ -976,9 +983,62 @@ static VALUE setnonblock(VALUE self, VALUE nb)
976
983
  return nb;
977
984
  }
978
985
 
986
+ static VALUE tryinit(int argc, VALUE *argv, VALUE self)
987
+ {
988
+ init(argc, argv, self);
989
+ setnonblock(self, Qtrue);
990
+
991
+ return self;
992
+ }
993
+
994
+ /*
995
+ * call-seq:
996
+ * mq.trysend(string [,priority[, timeout]]) => +true+ or +false+
997
+ *
998
+ * Exactly like POSIX_MQ#send, except it returns +false+ instead of raising
999
+ * +Errno::EAGAIN+ when non-blocking operation is desired and returns +true+
1000
+ * on success instead of +nil+.
1001
+ * This does not guarantee non-blocking behavior, the message queue must
1002
+ * be made non-blocking before calling this method.
1003
+ */
1004
+ static VALUE trysend(int argc, VALUE *argv, VALUE self)
1005
+ {
1006
+ _send(PMQ_TRY, argc, argv, self);
1007
+ }
1008
+
1009
+ /*
1010
+ * call-seq:
1011
+ * mq.tryshift([buffer [, timeout]]) => message or nil
1012
+ *
1013
+ * Exactly like POSIX_MQ#shift, except it returns +nil+ instead of raising
1014
+ * +Errno::EAGAIN+ when non-blocking operation is desired.
1015
+ *
1016
+ * This does not guarantee non-blocking behavior, the message queue must
1017
+ * be made non-blocking before calling this method.
1018
+ */
1019
+ static VALUE tryshift(int argc, VALUE *argv, VALUE self)
1020
+ {
1021
+ return _receive(PMQ_TRY, argc, argv, self);
1022
+ }
1023
+
1024
+ /*
1025
+ * call-seq:
1026
+ * mq.tryreceive([buffer [, timeout]]) => [ message, priority ] or nil
1027
+ *
1028
+ * Exactly like POSIX_MQ#receive, except it returns +nil+ instead of raising
1029
+ * +Errno::EAGAIN+ when non-blocking operation is desired.
1030
+ *
1031
+ * This does not guarantee non-blocking behavior, the message queue must
1032
+ * be made non-blocking before calling this method.
1033
+ */
1034
+ static VALUE tryreceive(int argc, VALUE *argv, VALUE self)
1035
+ {
1036
+ return _receive(PMQ_WANTARRAY|PMQ_TRY, argc, argv, self);
1037
+ }
1038
+
979
1039
  void Init_posix_mq_ext(void)
980
1040
  {
981
- cPOSIX_MQ = rb_define_class("POSIX_MQ", rb_cObject);
1041
+ VALUE cPOSIX_MQ = rb_define_class("POSIX_MQ", rb_cObject);
982
1042
  rb_define_alloc_func(cPOSIX_MQ, alloc);
983
1043
  cAttr = rb_const_get(cPOSIX_MQ, rb_intern("Attr"));
984
1044
 
@@ -1003,10 +1063,13 @@ void Init_posix_mq_ext(void)
1003
1063
  rb_define_singleton_method(cPOSIX_MQ, "unlink", s_unlink, 1);
1004
1064
 
1005
1065
  rb_define_method(cPOSIX_MQ, "initialize", init, -1);
1006
- rb_define_method(cPOSIX_MQ, "send", _send, -1);
1066
+ rb_define_method(cPOSIX_MQ, "send", my_send, -1);
1007
1067
  rb_define_method(cPOSIX_MQ, "<<", send0, 1);
1068
+ rb_define_method(cPOSIX_MQ, "trysend", trysend, -1);
1008
1069
  rb_define_method(cPOSIX_MQ, "receive", receive, -1);
1070
+ rb_define_method(cPOSIX_MQ, "tryreceive", tryreceive, -1);
1009
1071
  rb_define_method(cPOSIX_MQ, "shift", shift, -1);
1072
+ rb_define_method(cPOSIX_MQ, "tryshift", tryshift, -1);
1010
1073
  rb_define_method(cPOSIX_MQ, "attr", getattr, 0);
1011
1074
  rb_define_method(cPOSIX_MQ, "attr=", setattr, 1);
1012
1075
  rb_define_method(cPOSIX_MQ, "close", _close, 0);
@@ -1017,7 +1080,7 @@ void Init_posix_mq_ext(void)
1017
1080
  rb_define_method(cPOSIX_MQ, "nonblock=", setnonblock, 1);
1018
1081
  rb_define_method(cPOSIX_MQ, "notify_exec", setnotify_exec, 2);
1019
1082
  rb_define_method(cPOSIX_MQ, "notify_cleanup", notify_cleanup, 0);
1020
- rb_define_method(cPOSIX_MQ, "nonblock?", getnonblock, 0);
1083
+ rb_define_method(cPOSIX_MQ, "nonblock?", nonblock_p, 0);
1021
1084
  #ifdef MQD_TO_FD
1022
1085
  rb_define_method(cPOSIX_MQ, "to_io", to_io, 0);
1023
1086
  #endif
data/lib/posix_mq.rb CHANGED
@@ -6,11 +6,6 @@
6
6
  # See the link:README for examples on how to use it.
7
7
  class POSIX_MQ
8
8
 
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"
13
-
14
9
  # An analogous Struct to "struct mq_attr" in C.
15
10
  # This may be used in arguments for POSIX_MQ.new and
16
11
  # POSIX_MQ#attr=. POSIX_MQ#attr returns an instance
@@ -4,6 +4,11 @@ require 'posix_mq'
4
4
  require 'thread'
5
5
  require 'fcntl'
6
6
  $stderr.sync = $stdout.sync = true
7
+ require "dl"
8
+ begin
9
+ require "dl/func"
10
+ rescue LoadError
11
+ end
7
12
 
8
13
  class Test_POSIX_MQ < Test::Unit::TestCase
9
14
 
@@ -97,21 +102,24 @@ class Test_POSIX_MQ < Test::Unit::TestCase
97
102
  end
98
103
 
99
104
  def test_alarm_signal_safe
100
- alarm = nil
101
- libcs = %w(/lib/libc-2.7.so /usr/lib/libc.sl)
102
- libcs.each do |libc|
103
- if File.readable?(libc)
104
- require "dl"
105
- libc = DL.dlopen libc
105
+ libc = alarm = nil
106
+ libcs = %w(libc.so.6 /usr/lib/libc.sl)
107
+ libcs.each do |name|
108
+ libc = DL::Handle.new(name) rescue next
109
+ if defined?(DL::Function)
110
+ alarm = libc["alarm"]
111
+ alarm = DL::CFunc.new(alarm, DL::TYPE_INT, "alarm")
112
+ alarm = DL::Function.new(alarm, [DL::TYPE_INT], DL::TYPE_INT)
113
+ else
106
114
  alarm = libc["alarm", "II"]
107
- break
108
115
  end
116
+ break
109
117
  end
110
118
  alarm or return warn "alarm() not found in #{libcs.inspect}"
111
119
  alarms = 0
112
120
  trap("ALRM") { alarms += 1 }
113
121
  interval = 1
114
- alarm[interval]
122
+ alarm.call interval
115
123
  @mq = POSIX_MQ.new(@path, :rw)
116
124
  assert ! @mq.nonblock?
117
125
  t0 = Time.now
@@ -277,6 +285,17 @@ class Test_POSIX_MQ < Test::Unit::TestCase
277
285
  assert_equal 0, @mq.attr.flags
278
286
  end
279
287
 
288
+ def test_setattr_fork
289
+ @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY, 0666
290
+ mq_attr = POSIX_MQ::Attr.new(IO::NONBLOCK)
291
+ @mq.attr = mq_attr
292
+ assert @mq.nonblock?
293
+
294
+ pid = fork { @mq.nonblock = false }
295
+ assert Process.waitpid2(pid)[1].success?
296
+ assert ! @mq.nonblock?
297
+ end
298
+
280
299
  def test_new_nonblocking
281
300
  @mq = POSIX_MQ.new @path, IO::CREAT|IO::WRONLY|IO::NONBLOCK, 0666
282
301
  assert @mq.nonblock?
@@ -337,6 +356,20 @@ class Test_POSIX_MQ < Test::Unit::TestCase
337
356
  assert_raises(Errno::EAGAIN) { @mq << '.' }
338
357
  end
339
358
 
359
+ def test_try
360
+ mq_attr = POSIX_MQ::Attr.new(IO::NONBLOCK, 1, 1, 0)
361
+ @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666, mq_attr
362
+
363
+ assert_nil @mq.tryreceive
364
+ assert_nil @mq.tryshift
365
+ assert_equal true, @mq.trysend("a")
366
+ assert_equal [ "a", 0 ], @mq.tryreceive
367
+ assert_equal true, @mq.trysend("b")
368
+ assert_equal "b", @mq.tryshift
369
+ assert_equal true, @mq.trysend("c")
370
+ assert_equal false, @mq.trysend("d")
371
+ end
372
+
340
373
  def test_prio_max
341
374
  min_posix_mq_prio_max = 31 # defined by POSIX
342
375
  assert POSIX_MQ::PRIO_MAX >= min_posix_mq_prio_max
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: posix_mq
3
3
  version: !ruby/object:Gem::Version
4
- hash: 3
5
- prerelease:
4
+ hash: 961915908
5
+ prerelease: 5
6
6
  segments:
7
7
  - 0
8
- - 7
8
+ - 8
9
9
  - 0
10
- version: 0.7.0
10
+ - pre
11
+ version: 0.8.0pre
11
12
  platform: ruby
12
13
  authors:
13
14
  - Ruby POSIX MQ hackers
@@ -15,7 +16,7 @@ autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2011-02-24 00:00:00 +00:00
19
+ date: 2011-02-27 00:00:00 +00:00
19
20
  default_executable:
20
21
  dependencies:
21
22
  - !ruby/object:Gem::Dependency
@@ -102,12 +103,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
102
103
  required_rubygems_version: !ruby/object:Gem::Requirement
103
104
  none: false
104
105
  requirements:
105
- - - ">="
106
+ - - ">"
106
107
  - !ruby/object:Gem::Version
107
- hash: 3
108
+ hash: 25
108
109
  segments:
109
- - 0
110
- version: "0"
110
+ - 1
111
+ - 3
112
+ - 1
113
+ version: 1.3.1
111
114
  requirements: []
112
115
 
113
116
  rubyforge_project: qrp