mqueue 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.travis.yml +5 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +21 -0
- data/README.md +111 -0
- data/Rakefile +15 -0
- data/bin/console +9 -0
- data/bin/setup +8 -0
- data/ext/mqueue/extconf.rb +9 -0
- data/ext/mqueue/mq.h +46 -0
- data/ext/mqueue/mqueue.c +245 -0
- data/lib/mqueue.rb +21 -0
- data/lib/mqueue/version.rb +3 -0
- data/mqueue.gemspec +35 -0
- metadata +104 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5f419f642dfc73f8a2e09c836decc951a51d2030
|
4
|
+
data.tar.gz: ac1b186869ebe184375682db89822aafbb1864cd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 09ecda38f19e15ba0c4bc2efc97b4d12482d0185fe990035edc8c267f2ad6f2485fd1c90effae3fcd47ea0b3fd3422e5f76e290f56314904554831224e387044
|
7
|
+
data.tar.gz: 3a859cdd4ee599e02b2f8bf3c6f3a3899baed76bbce4961e3390cc2f7dfab1c8f3fcf16fe0e606c152f2de69c32bb5e834c4981b87407e611e1a9b309b07d218
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in mqueue.gemspec
|
4
|
+
gemspec
|
5
|
+
gem 'pry-nav', group: [:development, :test]
|
6
|
+
gem 'bundler', group: [:development, :test]
|
7
|
+
gem 'minitest', group: [:development, :test]
|
8
|
+
gem 'rake-compiler', group: [:development, :test]
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Irfan Sharif
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
# GEM: mqueue 
|
2
|
+
|
3
|
+
Lightweight wrapper built around [POSIX message queues](http://man7.org/linux/man-pages/man7/mq_overview.7.html). Abstracted functionality when designing a module for Ruby IPC with concurrent processes, reference used was [The Linux Programming Interface](http://man7.org/tlpi/download/TLPI-52-POSIX_Message_Queues.pdf).
|
4
|
+
|
5
|
+
Highlighted features:
|
6
|
+
|
7
|
+
* POSIX messages have associated priorities, messages are always strictly queued (and received) in priority order
|
8
|
+
* POSIX message queues have associated sets of attributes that can be set when the queue is created or opened
|
9
|
+
* Allows a process to register for message notification
|
10
|
+
from a queue. After registering, the process is notified of the availability of a message
|
11
|
+
by delivery of a signal or by the invocation of a function in a separate thread
|
12
|
+
* Ridiculously fast, everything is delegated to the kernel
|
13
|
+
*
|
14
|
+
|
15
|
+
**NOTE:** At the time of writing there already existed a [wrapper](https://github.com/Sirupsen/posix-mqueue) around POSIX message queues but didn't offer some of the notification subscription functionality I needed for IPC, while I could've opted to add that into the original (you'll notice a lot of overlap), I wanted to experiment with C extensions in ruby for some other libraries I'm going to be working on in the future, messaging queues was a subject I was sufficiently versed it to start with.
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
Add this line to your application's Gemfile:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
gem 'mqueue'
|
23
|
+
```
|
24
|
+
|
25
|
+
And then execute:
|
26
|
+
|
27
|
+
$ bundle
|
28
|
+
|
29
|
+
Or install it yourself as:
|
30
|
+
|
31
|
+
$ gem install mqueue
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
require 'mqueue'
|
37
|
+
|
38
|
+
# Queue names must start with '/', shown below are the default settings
|
39
|
+
provided # by the Kernel (except for queue_name), check below for options
|
40
|
+
available for flags and how to change # default settings outside ruby
|
41
|
+
mq = MQueue.new("/queue_name", capacity: 10, max_msgsize: 8192, flags: [:creat, :rdwr])
|
42
|
+
mq.send "message"
|
43
|
+
|
44
|
+
mq.receive
|
45
|
+
# => "message"
|
46
|
+
|
47
|
+
fork { mq.send "another one" }
|
48
|
+
|
49
|
+
# Blocks on empty queues, in this case until forked process adds message onto queue
|
50
|
+
mq.recieve
|
51
|
+
# => "another one"
|
52
|
+
|
53
|
+
10.times do
|
54
|
+
mq.send "42"
|
55
|
+
end
|
56
|
+
|
57
|
+
mq.size
|
58
|
+
# => 10
|
59
|
+
|
60
|
+
# Timed send takes an optional parameter indicating duration it would wait
|
61
|
+
# (in seconds) before returning false, defaults to 0
|
62
|
+
refute mq.timedsend "queue full, this will fail", 0
|
63
|
+
|
64
|
+
mq.full?
|
65
|
+
# => true
|
66
|
+
|
67
|
+
# This would block indefinitely until something is removed from the queue
|
68
|
+
# mq.send "the answer to life"
|
69
|
+
|
70
|
+
# Empties queue of all messages, includes pending messages
|
71
|
+
mq.flush
|
72
|
+
|
73
|
+
# Timed receive takes an optional parameter indicating duration it would wait
|
74
|
+
# (in seconds) before returning false, defaults to 0
|
75
|
+
refute mq.timedreceive "queue empty, this will fail too", 0
|
76
|
+
|
77
|
+
mq.empty?
|
78
|
+
# => true
|
79
|
+
|
80
|
+
# Notification as defined here is when a message is added to previously empty
|
81
|
+
# queue, will not get triggered if someone else is waiting on `receive` or
|
82
|
+
# messages added to non-empty queues. is triggered asynchronously, only one
|
83
|
+
# process will be able to add the notification hook to a particular queue (NOT IMPLEMENTED)
|
84
|
+
mq.on_notification do |msg|
|
85
|
+
puts "#{msg} delivered through notification hook"
|
86
|
+
end
|
87
|
+
|
88
|
+
mq.send "notification"
|
89
|
+
# => "notification delivered through notification hook"
|
90
|
+
|
91
|
+
# Hook no longer triggered (NOT IMPLEMENTED)
|
92
|
+
mq.disable_notification
|
93
|
+
mq.send "ignored notification"
|
94
|
+
|
95
|
+
# Deletes the queue and any containing messages, if not done so it persists until system reboot
|
96
|
+
mq.delete
|
97
|
+
```
|
98
|
+
|
99
|
+
## Development
|
100
|
+
|
101
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
102
|
+
|
103
|
+
## Contributing
|
104
|
+
|
105
|
+
Bug reports and pull requests are welcome on GitHub at [irfansharif](https://github.com/irfansharif/mqueue).
|
106
|
+
|
107
|
+
|
108
|
+
## License
|
109
|
+
|
110
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
111
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/extensiontask"
|
3
|
+
require "rake/testtask"
|
4
|
+
|
5
|
+
Rake::TestTask.new(:test) do |t|
|
6
|
+
t.libs << "test"
|
7
|
+
t.libs << "lib"
|
8
|
+
t.test_files = FileList['test/**/*_test.rb']
|
9
|
+
end
|
10
|
+
|
11
|
+
Rake::ExtensionTask.new "mqueue" do |ext|
|
12
|
+
ext.lib_dir = "lib/mqueue"
|
13
|
+
end
|
14
|
+
|
15
|
+
task :default => :test
|
data/bin/console
ADDED
data/bin/setup
ADDED
data/ext/mqueue/mq.h
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
#ifndef MQUEUE
|
2
|
+
#define MQUEUE
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
#include <fcntl.h> /* Defines O_* constants */
|
6
|
+
#include <sys/stat.h> /* Defines mode constants */
|
7
|
+
#include <mqueue.h>
|
8
|
+
#include <unistd.h>
|
9
|
+
#include <time.h>
|
10
|
+
#include <pthread.h>
|
11
|
+
|
12
|
+
typedef struct {
|
13
|
+
mqd_t queue_descriptor;
|
14
|
+
struct mq_attr attributes;
|
15
|
+
char* queue_name;
|
16
|
+
} mqueue_t;
|
17
|
+
|
18
|
+
static void free_mqueue(void*);
|
19
|
+
size_t size_mqueue(const void*);
|
20
|
+
long generate_flags(VALUE);
|
21
|
+
static void notification_function(union sigval);
|
22
|
+
|
23
|
+
static const rb_data_type_t
|
24
|
+
mqueue_data_type = {
|
25
|
+
"mqueue_data_type",
|
26
|
+
{
|
27
|
+
0,
|
28
|
+
free_mqueue,
|
29
|
+
size_mqueue
|
30
|
+
}
|
31
|
+
};
|
32
|
+
|
33
|
+
void Init_mqueue();
|
34
|
+
static VALUE alloc_mqueue(VALUE);
|
35
|
+
VALUE mqueue_initialize(int, VALUE*, VALUE);
|
36
|
+
|
37
|
+
VALUE mqueue_send(VALUE, VALUE);
|
38
|
+
VALUE mqueue_receive(VALUE);
|
39
|
+
VALUE mqueue_timedsend(int, VALUE*, VALUE);
|
40
|
+
VALUE mqueue_timedreceive(int, VALUE*, VALUE);
|
41
|
+
VALUE mqueue_size(VALUE);
|
42
|
+
VALUE mqueue_capacity(VALUE);
|
43
|
+
VALUE mqueue_max_msgsize(VALUE);
|
44
|
+
VALUE mqueue_delete(VALUE);
|
45
|
+
|
46
|
+
#endif
|
data/ext/mqueue/mqueue.c
ADDED
@@ -0,0 +1,245 @@
|
|
1
|
+
#include "mq.h"
|
2
|
+
|
3
|
+
void
|
4
|
+
Init_mqueue() {
|
5
|
+
VALUE mqueue = rb_define_class("MQueue", rb_cObject);
|
6
|
+
rb_define_alloc_func(mqueue, alloc_mqueue);
|
7
|
+
|
8
|
+
rb_define_method(mqueue, "initialize", mqueue_initialize, -1);
|
9
|
+
rb_define_method(mqueue, "send", mqueue_send, 1);
|
10
|
+
rb_define_method(mqueue, "receive", mqueue_receive, 0);
|
11
|
+
rb_define_method(mqueue, "timedsend", mqueue_timedsend, -1);
|
12
|
+
rb_define_method(mqueue, "timedreceive", mqueue_timedreceive, -1);
|
13
|
+
rb_define_method(mqueue, "size", mqueue_size, 0);
|
14
|
+
rb_define_method(mqueue, "capacity", mqueue_capacity, 0);
|
15
|
+
rb_define_method(mqueue, "max_msgsize", mqueue_max_msgsize, 0);
|
16
|
+
rb_define_method(mqueue, "delete", mqueue_delete, 0);
|
17
|
+
}
|
18
|
+
|
19
|
+
static VALUE
|
20
|
+
alloc_mqueue(VALUE klass) {
|
21
|
+
mqueue_t* queue_ptr;
|
22
|
+
VALUE object = TypedData_Make_Struct(klass, mqueue_t, &mqueue_data_type, queue_ptr);
|
23
|
+
|
24
|
+
(*queue_ptr).queue_descriptor = -1;
|
25
|
+
(*queue_ptr).queue_name = NULL;
|
26
|
+
(*queue_ptr).attributes.mq_curmsgs = 0;
|
27
|
+
(*queue_ptr).attributes.mq_flags = 0;
|
28
|
+
|
29
|
+
return object;
|
30
|
+
}
|
31
|
+
|
32
|
+
VALUE
|
33
|
+
mqueue_initialize(int argc, VALUE* argv, VALUE self) {
|
34
|
+
VALUE queue_name, options;
|
35
|
+
mqueue_t* queue_ptr;
|
36
|
+
|
37
|
+
rb_scan_args(argc, argv, "1:", &queue_name, &options);
|
38
|
+
TypedData_Get_Struct(self, mqueue_t, &mqueue_data_type, queue_ptr);
|
39
|
+
|
40
|
+
if ((*queue_ptr).queue_descriptor != -1)
|
41
|
+
rb_raise(rb_eRuntimeError, "Illegal initialization");
|
42
|
+
|
43
|
+
if (TYPE(queue_name) != T_STRING)
|
44
|
+
rb_raise(rb_eTypeError, "Invalid queue name, must be a string");
|
45
|
+
if (TYPE(options) != T_HASH)
|
46
|
+
options = rb_hash_new();
|
47
|
+
|
48
|
+
(*queue_ptr).queue_name = ruby_strdup(StringValueCStr(queue_name));
|
49
|
+
(*queue_ptr).attributes.mq_maxmsg = FIX2INT(rb_hash_lookup2(options,
|
50
|
+
ID2SYM(rb_intern("capacity")),
|
51
|
+
INT2NUM(10))
|
52
|
+
);
|
53
|
+
(*queue_ptr).attributes.mq_msgsize = FIX2INT(rb_hash_lookup2(options,
|
54
|
+
ID2SYM(rb_intern("max_msgsize")),
|
55
|
+
INT2NUM(4096))
|
56
|
+
);
|
57
|
+
(*queue_ptr).attributes.mq_flags = generate_flags(options);
|
58
|
+
(*queue_ptr).queue_descriptor = mq_open((*queue_ptr).queue_name,
|
59
|
+
(*queue_ptr).attributes.mq_flags,
|
60
|
+
S_IRUSR | S_IWUSR,
|
61
|
+
&(*queue_ptr).attributes
|
62
|
+
);
|
63
|
+
|
64
|
+
if ((*queue_ptr).queue_descriptor == (mqd_t)-1)
|
65
|
+
rb_raise(rb_eRuntimeError, "Unable to initialize");
|
66
|
+
|
67
|
+
return self;
|
68
|
+
}
|
69
|
+
|
70
|
+
VALUE
|
71
|
+
mqueue_delete(VALUE self) {
|
72
|
+
mqueue_t* queue_ptr;
|
73
|
+
TypedData_Get_Struct(self, mqueue_t, &mqueue_data_type, queue_ptr);
|
74
|
+
|
75
|
+
if (mq_unlink((*queue_ptr).queue_name) == -1)
|
76
|
+
return Qfalse;
|
77
|
+
|
78
|
+
return Qtrue;
|
79
|
+
}
|
80
|
+
|
81
|
+
VALUE
|
82
|
+
mqueue_send(VALUE self, VALUE message) {
|
83
|
+
mqueue_t* queue_ptr;
|
84
|
+
char* msg_ptr;
|
85
|
+
size_t msg_len;
|
86
|
+
|
87
|
+
TypedData_Get_Struct(self, mqueue_t, &mqueue_data_type, queue_ptr);
|
88
|
+
|
89
|
+
msg_ptr = RSTRING_PTR(message);
|
90
|
+
msg_len = RSTRING_LEN(message);
|
91
|
+
|
92
|
+
if (mq_send((*queue_ptr).queue_descriptor, msg_ptr, msg_len, 0) == -1)
|
93
|
+
return Qfalse;
|
94
|
+
return Qtrue;
|
95
|
+
}
|
96
|
+
|
97
|
+
VALUE
|
98
|
+
mqueue_receive(VALUE self) {
|
99
|
+
mqueue_t* queue_ptr;
|
100
|
+
int len;
|
101
|
+
|
102
|
+
TypedData_Get_Struct(self, mqueue_t, &mqueue_data_type, queue_ptr);
|
103
|
+
char msg_buffer[(*queue_ptr).attributes.mq_msgsize];
|
104
|
+
|
105
|
+
if ((len = mq_receive((*queue_ptr).queue_descriptor, msg_buffer, (*queue_ptr).attributes.mq_msgsize, 0)) == -1)
|
106
|
+
return Qfalse;
|
107
|
+
|
108
|
+
return rb_str_new(msg_buffer, len);
|
109
|
+
}
|
110
|
+
|
111
|
+
VALUE
|
112
|
+
mqueue_timedsend(int argc, VALUE* argv, VALUE self) {
|
113
|
+
VALUE message, timeout;
|
114
|
+
mqueue_t* queue_ptr;
|
115
|
+
char* msg_ptr;
|
116
|
+
size_t msg_len;
|
117
|
+
struct timespec abs_timeout;
|
118
|
+
|
119
|
+
rb_scan_args(argc, argv, "11", &message, &timeout);
|
120
|
+
|
121
|
+
if (NIL_P(timeout))
|
122
|
+
timeout = INT2NUM(10);
|
123
|
+
|
124
|
+
TypedData_Get_Struct(self, mqueue_t, &mqueue_data_type, queue_ptr);
|
125
|
+
|
126
|
+
msg_ptr = RSTRING_PTR(message);
|
127
|
+
msg_len = RSTRING_LEN(message);
|
128
|
+
|
129
|
+
if (clock_gettime(CLOCK_REALTIME, &abs_timeout) == -1)
|
130
|
+
return Qfalse;
|
131
|
+
|
132
|
+
abs_timeout.tv_sec += NUM2INT(timeout);
|
133
|
+
|
134
|
+
if (mq_timedsend((*queue_ptr).queue_descriptor, msg_ptr, msg_len, 0, &abs_timeout) == -1)
|
135
|
+
return Qfalse;
|
136
|
+
return Qtrue;
|
137
|
+
}
|
138
|
+
|
139
|
+
VALUE
|
140
|
+
mqueue_timedreceive(int argc, VALUE* argv, VALUE self) {
|
141
|
+
VALUE timeout;
|
142
|
+
mqueue_t* queue_ptr;
|
143
|
+
struct timespec abs_timeout;
|
144
|
+
|
145
|
+
rb_scan_args(argc, argv, "01", &timeout);
|
146
|
+
|
147
|
+
if (NIL_P(timeout))
|
148
|
+
timeout = INT2NUM(10);
|
149
|
+
|
150
|
+
TypedData_Get_Struct(self, mqueue_t, &mqueue_data_type, queue_ptr);
|
151
|
+
char msg_buffer[(*queue_ptr).attributes.mq_msgsize];
|
152
|
+
|
153
|
+
if (clock_gettime(CLOCK_REALTIME, &abs_timeout) == -1)
|
154
|
+
return Qfalse;
|
155
|
+
|
156
|
+
abs_timeout.tv_sec += NUM2INT(timeout);
|
157
|
+
if (mq_timedreceive((*queue_ptr).queue_descriptor, msg_buffer, (*queue_ptr).attributes.mq_msgsize, 0, &abs_timeout) == -1)
|
158
|
+
return Qfalse;
|
159
|
+
|
160
|
+
return rb_str_new_cstr(msg_buffer);
|
161
|
+
}
|
162
|
+
|
163
|
+
VALUE
|
164
|
+
mqueue_size(VALUE self) {
|
165
|
+
mqueue_t* queue_ptr;
|
166
|
+
struct mq_attr attributes;
|
167
|
+
|
168
|
+
TypedData_Get_Struct(self, mqueue_t, &mqueue_data_type, queue_ptr);
|
169
|
+
|
170
|
+
if (mq_getattr((*queue_ptr).queue_descriptor, &attributes) == -1)
|
171
|
+
return INT2NUM(-1);
|
172
|
+
|
173
|
+
return INT2NUM(attributes.mq_curmsgs);
|
174
|
+
}
|
175
|
+
|
176
|
+
VALUE
|
177
|
+
mqueue_capacity(VALUE self) {
|
178
|
+
mqueue_t* queue_ptr;
|
179
|
+
struct mq_attr attributes;
|
180
|
+
|
181
|
+
TypedData_Get_Struct(self, mqueue_t, &mqueue_data_type, queue_ptr);
|
182
|
+
|
183
|
+
if (mq_getattr((*queue_ptr).queue_descriptor, &attributes) == -1)
|
184
|
+
return INT2NUM(-1);
|
185
|
+
|
186
|
+
return INT2NUM(attributes.mq_maxmsg);
|
187
|
+
}
|
188
|
+
|
189
|
+
VALUE
|
190
|
+
mqueue_max_msgsize(VALUE self) {
|
191
|
+
mqueue_t* queue_ptr;
|
192
|
+
struct mq_attr attributes;
|
193
|
+
|
194
|
+
TypedData_Get_Struct(self, mqueue_t, &mqueue_data_type, queue_ptr);
|
195
|
+
|
196
|
+
if (mq_getattr((*queue_ptr).queue_descriptor, &attributes) == -1)
|
197
|
+
return INT2NUM(-1);
|
198
|
+
|
199
|
+
return INT2NUM(attributes.mq_msgsize);
|
200
|
+
}
|
201
|
+
|
202
|
+
/******************************************************************************/
|
203
|
+
|
204
|
+
static void
|
205
|
+
free_mqueue (void* ptr) {
|
206
|
+
mqueue_t* queue_ptr = ptr;
|
207
|
+
if (mq_close((*queue_ptr).queue_descriptor) == -1)
|
208
|
+
rb_sys_fail("mq_close failed");
|
209
|
+
|
210
|
+
free((*queue_ptr).queue_name);
|
211
|
+
free(ptr);
|
212
|
+
}
|
213
|
+
|
214
|
+
size_t
|
215
|
+
size_mqueue (const void* ptr) {
|
216
|
+
mqueue_t* queue_ptr = queue_ptr;
|
217
|
+
return sizeof(mqueue_t) + sizeof(char) * strlen((*queue_ptr).queue_name);
|
218
|
+
}
|
219
|
+
|
220
|
+
long
|
221
|
+
generate_flags(VALUE options) {
|
222
|
+
VALUE flags = rb_hash_lookup(options, ID2SYM(rb_intern("flags"))), cur_flag;
|
223
|
+
if (flags == Qnil || RARRAY_LEN(flags) == 0)
|
224
|
+
return 0;
|
225
|
+
int num_flags = RARRAY_LEN(flags), i;
|
226
|
+
long mq_flags = 0;
|
227
|
+
|
228
|
+
for(i = 0; i < num_flags; i++) {
|
229
|
+
cur_flag = rb_ary_entry(flags, i);
|
230
|
+
if (cur_flag == ID2SYM(rb_intern("creat")))
|
231
|
+
mq_flags |= O_CREAT;
|
232
|
+
else if (cur_flag == ID2SYM(rb_intern("excl")))
|
233
|
+
mq_flags |= O_EXCL;
|
234
|
+
else if (cur_flag == ID2SYM(rb_intern("rdonly")))
|
235
|
+
mq_flags |= O_RDONLY;
|
236
|
+
else if (cur_flag == ID2SYM(rb_intern("wronly")))
|
237
|
+
mq_flags |= O_WRONLY;
|
238
|
+
else if (cur_flag == ID2SYM(rb_intern("rdwr")))
|
239
|
+
mq_flags |= O_RDWR;
|
240
|
+
else if (cur_flag == ID2SYM(rb_intern("nonblock")))
|
241
|
+
mq_flags |= O_NONBLOCK;
|
242
|
+
}
|
243
|
+
|
244
|
+
return mq_flags;
|
245
|
+
}
|
data/lib/mqueue.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require "mqueue/mqueue"
|
2
|
+
|
3
|
+
module MQueueExtensions
|
4
|
+
def flush
|
5
|
+
values = []
|
6
|
+
values << timedreceive(0) while size > 0
|
7
|
+
values
|
8
|
+
end
|
9
|
+
|
10
|
+
def full?
|
11
|
+
size == capacity
|
12
|
+
end
|
13
|
+
|
14
|
+
def empty?
|
15
|
+
size == 0
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class MQueue
|
20
|
+
prepend MQueueExtensions
|
21
|
+
end
|
data/mqueue.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'mqueue/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "mqueue"
|
8
|
+
spec.version = MQueue::VERSION
|
9
|
+
spec.authors = ["Irfan Sharif"]
|
10
|
+
spec.email = ["irfanmahmoudsharif@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Ruby wrapper around POSIX IPC message queue}
|
13
|
+
spec.description = %q{Lightweight wrapper built around POSIX message queues.
|
14
|
+
Reference used was The Linux Programming Interface.}
|
15
|
+
spec.homepage = "https://github.com/irfansharif/mqueue"
|
16
|
+
spec.license = "MIT"
|
17
|
+
|
18
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
19
|
+
# delete this section to allow pushing this gem to any host.
|
20
|
+
if spec.respond_to?(:metadata)
|
21
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
22
|
+
else
|
23
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
24
|
+
end
|
25
|
+
|
26
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
27
|
+
spec.bindir = "exe"
|
28
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
29
|
+
spec.extensions = %w[ext/mqueue/extconf.rb]
|
30
|
+
spec.require_paths = ["lib"]
|
31
|
+
|
32
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
33
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
34
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mqueue
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Irfan Sharif
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-05-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.11'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.11'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.0'
|
55
|
+
description: |-
|
56
|
+
Lightweight wrapper built around POSIX message queues.
|
57
|
+
Reference used was The Linux Programming Interface.
|
58
|
+
email:
|
59
|
+
- irfanmahmoudsharif@gmail.com
|
60
|
+
executables: []
|
61
|
+
extensions:
|
62
|
+
- ext/mqueue/extconf.rb
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- ".gitignore"
|
66
|
+
- ".travis.yml"
|
67
|
+
- Gemfile
|
68
|
+
- LICENSE.txt
|
69
|
+
- README.md
|
70
|
+
- Rakefile
|
71
|
+
- bin/console
|
72
|
+
- bin/setup
|
73
|
+
- ext/mqueue/extconf.rb
|
74
|
+
- ext/mqueue/mq.h
|
75
|
+
- ext/mqueue/mqueue.c
|
76
|
+
- lib/mqueue.rb
|
77
|
+
- lib/mqueue/version.rb
|
78
|
+
- mqueue.gemspec
|
79
|
+
homepage: https://github.com/irfansharif/mqueue
|
80
|
+
licenses:
|
81
|
+
- MIT
|
82
|
+
metadata:
|
83
|
+
allowed_push_host: https://rubygems.org
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 2.6.2
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: Ruby wrapper around POSIX IPC message queue
|
104
|
+
test_files: []
|