posix_mq 0.7.0 → 0.8.0pre
Sign up to get free protection for your applications and to get access to all the features.
- data/.wrongdoc.yml +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/ext/posix_mq/posix_mq.c +95 -32
- data/lib/posix_mq.rb +0 -5
- data/test/test_posix_mq.rb +41 -8
- metadata +12 -9
data/.wrongdoc.yml
CHANGED
data/GIT-VERSION-GEN
CHANGED
data/ext/posix_mq/posix_mq.c
CHANGED
@@ -62,10 +62,13 @@ static int MQ_IO_CLOSE(struct posix_mq *mq)
|
|
62
62
|
}
|
63
63
|
#endif
|
64
64
|
|
65
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
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
|
-
|
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
|
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(
|
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
|
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
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
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 (
|
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
|
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",
|
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?",
|
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
|
data/test/test_posix_mq.rb
CHANGED
@@ -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(
|
102
|
-
libcs.each do |
|
103
|
-
|
104
|
-
|
105
|
-
|
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
|
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:
|
5
|
-
prerelease:
|
4
|
+
hash: 961915908
|
5
|
+
prerelease: 5
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 8
|
9
9
|
- 0
|
10
|
-
|
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-
|
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:
|
108
|
+
hash: 25
|
108
109
|
segments:
|
109
|
-
-
|
110
|
-
|
110
|
+
- 1
|
111
|
+
- 3
|
112
|
+
- 1
|
113
|
+
version: 1.3.1
|
111
114
|
requirements: []
|
112
115
|
|
113
116
|
rubyforge_project: qrp
|