mpipe 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 638f1385e64bf50aedff83fbdec7cf8de6f2e63b
4
+ data.tar.gz: e16b54cc652d0f6503cd4776bf716903fcaf2703
5
+ SHA512:
6
+ metadata.gz: df234ecdd079cb9b24f7afb9c8c1f8ce585cd247f6286a4c49e8484b5b7296ec2445ffb3cf603d5a2ef69be8dd567b6c8a03905f6c0d3a96b793869c76e2839f
7
+ data.tar.gz: 5872d1e9ab4b7536d50d55a9cb778a9d43cc140b81e6bdaed70388b19af051956039e03554338ee11399a8f56af39c40c10a9130f0e2bdca67deb0acc9172d7a
@@ -0,0 +1,49 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ tmp/
12
+
13
+ ## Specific to RubyMotion:
14
+ .dat*
15
+ .repl_history
16
+ build/
17
+
18
+ ## Documentation cache and generated files:
19
+ .yardoc/
20
+ _yardoc/
21
+ doc/
22
+ rdoc/
23
+
24
+ ## Environment normalization:
25
+ /.bundle/
26
+ /vendor/bundle
27
+ /lib/bundler/man/
28
+
29
+ # for a library or gem, you might want to ignore these files since the code is
30
+ # intended to run in multiple environments; otherwise, check them in:
31
+ Gemfile.lock
32
+ .ruby-version
33
+ .ruby-gemset
34
+
35
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
36
+ .rvmrc
37
+
38
+ # setup.rb
39
+ /SetupConfig
40
+ /SetupReceipt
41
+
42
+ # Build files for extension
43
+ *~
44
+ *.o
45
+ *.so
46
+ TAGS
47
+ t.rb
48
+ *.bak[0-9]
49
+ bak
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mpipe.gemspec
4
+ gemspec
@@ -0,0 +1,76 @@
1
+ # MPipe
2
+
3
+ Ruby's IO.pipe emulation over MPI
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'mpipe'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install mpipe
20
+
21
+ ## Usage
22
+
23
+ test code: t.rb
24
+ ```ruby
25
+ require "mpipe"
26
+
27
+ MPipe.init
28
+ rank = MPipe::Comm.rank
29
+ size = MPipe::Comm.size
30
+ puts "size=%d rank=%d pid=%d" % [size,rank,Process.pid]
31
+
32
+ if rank == 0
33
+
34
+ (1..size-1).each do |r|
35
+ p MPipe.new(r).read
36
+ end
37
+
38
+ else
39
+
40
+ sleep rank
41
+ MPipe.new(0).write("Hello from #{rank}")
42
+
43
+ end
44
+ ```
45
+
46
+ execute:
47
+ ```
48
+ $ mpirun -np 4 ruby t.rb
49
+ size=4 rank=0 pid=10353
50
+ "Hello from 1"
51
+ size=4 rank=1 pid=10354
52
+ "Hello from 2"
53
+ size=4 rank=2 pid=10355
54
+ "Hello from 3"
55
+ size=4 rank=3 pid=10356
56
+ ```
57
+
58
+ ## API
59
+
60
+ ```
61
+ MPipe.init(*args) -- calls MPI_Init()
62
+ MPipe.finalize -- calls MPI_Finalize()
63
+ MPipe.abort(errorcode) -- calls MPI_Abort(MPI_COMM_WORLD, errorcode)
64
+ MPipe::Comm.rank -- calls MPI_Comm_rank(), return the rank of this process.
65
+ MPipe::Comm.size -- calls MPI_Comm_size(), return the size of this environment.
66
+
67
+ mp = MPipe.new(rank) -- returns pipe to MPI process with rank.
68
+ mp.write(str) -- emulate IO#write.
69
+ mp.read(maxlen,outbuf) -- emulate IO#read.
70
+ mp.read_nonblock(maxlen,outbuf) -- emulate IO#read_nonblock.
71
+ MPipe.select(array_of_mpipe) -- emulate IO.select
72
+ ```
73
+
74
+ ## Contributing
75
+
76
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Masahiro TANAKA/mpipe.
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,9 @@
1
+ require "mkmf"
2
+
3
+ dir_config("mpi")
4
+
5
+ CONFIG['CC'] = "mpicc"
6
+
7
+ $objs = %w(mpipe.o)
8
+
9
+ create_makefile("mpipe")
@@ -0,0 +1,584 @@
1
+ #include "ruby.h"
2
+ #include "ruby/io.h"
3
+ //#include "ruby/encoding.h"
4
+ #include "mpi.h"
5
+
6
+ #define MPIPE_VERSION "0.1.0"
7
+
8
+ static int mp_buffer_size = 4098;
9
+ static int mp_initialized = 0;
10
+ static int mp_finalized = 0;
11
+ static VALUE sym_exception;
12
+ static VALUE eEAGAINWaitReadable;
13
+ static ID id_allocated_mpipe;
14
+
15
+ struct MPipe {
16
+ int rank;
17
+ char *send_buffer;
18
+ char *recv_buffer;
19
+ MPI_Request send_request;
20
+ MPI_Request recv_request;
21
+ int send_count;
22
+ int recv_count;
23
+ int recv_begin;
24
+ };
25
+
26
+ #define IS_MPIPE(obj) (rb_typeddata_is_kind_of((obj), &mp_data_type))
27
+ #define error_inval(msg) (rb_syserr_fail(EINVAL, msg))
28
+ //#define get_enc(ptr) ((ptr)->enc ? (ptr)->enc : rb_enc_get((ptr)->string))
29
+ #define get_enc(ptr) ((ptr)->enc)
30
+
31
+ static void
32
+ mp_finalize()
33
+ {
34
+ if (mp_initialized && !mp_finalized) {
35
+ mp_finalized = 1;
36
+ MPI_Finalize();
37
+ }
38
+ }
39
+
40
+ static VALUE
41
+ mp_mpi_init(int argc, VALUE *argv, VALUE klass)
42
+ {
43
+ char **cargv;
44
+ VALUE progname, mpipe_ary;
45
+ int i, size;
46
+
47
+ cargv = ALLOCA_N(char *, argc+1);
48
+ progname = rb_gv_get("$0");
49
+ cargv[0] = StringValueCStr(progname);
50
+
51
+ for(i=0; i<argc; i++) {
52
+ if (TYPE(argv[i]) == T_STRING) {
53
+ cargv[i+1] = StringValueCStr(argv[i]);
54
+ } else {
55
+ rb_raise(rb_eArgError, "argument must be string");
56
+ }
57
+ }
58
+ argc++;
59
+
60
+ MPI_Init(&argc, &cargv);
61
+
62
+ if (mp_initialized) {
63
+ return Qnil;
64
+ } else {
65
+ mp_initialized = 1;
66
+ }
67
+ atexit(mp_finalize);
68
+
69
+ MPI_Comm_size(MPI_COMM_WORLD, &size);
70
+ mpipe_ary = rb_ary_new2(size);
71
+ rb_ivar_set(klass, id_allocated_mpipe, mpipe_ary);
72
+
73
+ return Qnil;
74
+ }
75
+
76
+ static VALUE
77
+ mp_mpi_finalize(VALUE klass)
78
+ {
79
+ mp_finalize();
80
+ return Qnil;
81
+ }
82
+
83
+ static VALUE
84
+ mp_mpi_abort(VALUE klass, VALUE rerror)
85
+ {
86
+ int ierror;
87
+
88
+ ierror = MPI_Abort(MPI_COMM_WORLD, NUM2INT(rerror));
89
+ return INT2NUM(ierror);
90
+ }
91
+
92
+ static VALUE
93
+ mp_mpi_buffer_size(VALUE mod)
94
+ {
95
+ return INT2NUM(mp_buffer_size);
96
+ }
97
+
98
+ static VALUE
99
+ mp_mpi_set_buffer_size(VALUE mod, VALUE size)
100
+ {
101
+ if (mp_initialized) {
102
+ rb_raise(rb_eStandardError,"buffer_size must be set before MPipe.init");
103
+ }
104
+ mp_buffer_size = NUM2INT(size);
105
+ return size;
106
+ }
107
+
108
+ static VALUE
109
+ mp_comm_size(VALUE self)
110
+ {
111
+ int size;
112
+
113
+ MPI_Comm_size(MPI_COMM_WORLD, &size);
114
+ return INT2NUM(size);
115
+ }
116
+
117
+ static VALUE
118
+ mp_comm_rank(VALUE self)
119
+ {
120
+ int rank;
121
+
122
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
123
+ return INT2NUM(rank);
124
+ }
125
+
126
+ // ---------------------------------------------------------
127
+
128
+ static struct MPipe *
129
+ mp_alloc(void)
130
+ {
131
+ struct MPipe *ptr = ALLOC(struct MPipe);
132
+ ptr->rank = -1;
133
+ ptr->send_buffer = 0;
134
+ ptr->recv_buffer = 0;
135
+ ptr->send_count = 0;
136
+ ptr->recv_count = 0;
137
+ ptr->recv_begin = 0;
138
+ return ptr;
139
+ }
140
+
141
+ static void
142
+ mp_free(void *p)
143
+ {
144
+ struct MPipe *ptr = p;
145
+
146
+ //if (--ptr->count <= 0) {
147
+ if (ptr) {
148
+
149
+ if (ptr->send_count == -1) {
150
+ MPI_Request_free(&ptr->send_request);
151
+ ptr->send_count = 0;
152
+ }
153
+ if (ptr->recv_count == -1) {
154
+ MPI_Request_free(&ptr->recv_request);
155
+ ptr->recv_count = 0;
156
+ }
157
+ if (ptr->send_buffer) {
158
+ xfree(ptr->send_buffer);
159
+ ptr->send_buffer = 0;
160
+ }
161
+ if (ptr->recv_buffer) {
162
+ xfree(ptr->recv_buffer);
163
+ ptr->recv_buffer = 0;
164
+ }
165
+
166
+ xfree(ptr);
167
+ }
168
+ }
169
+
170
+ static size_t
171
+ mp_memsize(const void *p)
172
+ {
173
+ return sizeof(struct MPipe) + mp_buffer_size*2;
174
+ }
175
+
176
+ static const rb_data_type_t mp_data_type = {
177
+ "mpipe",
178
+ {
179
+ 0,
180
+ mp_free,
181
+ mp_memsize,
182
+ },
183
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
184
+ };
185
+
186
+ #define check_mpipe(self) ((struct MPipe*)rb_check_typeddata((self), &mp_data_type))
187
+
188
+ static struct MPipe*
189
+ get_mpipe(VALUE self)
190
+ {
191
+ struct MPipe *ptr = check_mpipe(rb_io_taint_check(self));
192
+
193
+ if (!ptr) {
194
+ rb_raise(rb_eIOError, "uninitialized stream");
195
+ }
196
+ return ptr;
197
+ }
198
+
199
+ #define MPipe(obj) get_mpipe(obj)
200
+
201
+ static VALUE
202
+ mp_s_allocate(VALUE klass)
203
+ {
204
+ return TypedData_Wrap_Struct(klass, &mp_data_type, 0);
205
+ }
206
+
207
+ static VALUE
208
+ mp_init(struct MPipe *ptr, VALUE self, VALUE rank)
209
+ {
210
+ ptr->rank = NUM2INT(rank);
211
+ ptr->send_buffer = malloc(mp_buffer_size);
212
+ ptr->recv_buffer = malloc(mp_buffer_size);
213
+ return self;
214
+ }
215
+
216
+ /*
217
+ * call-seq: MPipe.new(string=""[, mode])
218
+ *
219
+ * Creates new MPipe instance from with _string_ and _mode_.
220
+ */
221
+ static VALUE
222
+ mp_initialize(VALUE self, VALUE rank)
223
+ {
224
+ struct MPipe *ptr = check_mpipe(self);
225
+
226
+ if (!ptr) {
227
+ DATA_PTR(self) = ptr = mp_alloc();
228
+ }
229
+ rb_call_super(0, 0);
230
+ return mp_init(ptr, self, rank);
231
+ }
232
+
233
+ /* :nodoc: */
234
+ static VALUE
235
+ mp_s_new(VALUE klass, VALUE vrank)
236
+ {
237
+ VALUE mpipe, mpipe_ary;
238
+ int rank;
239
+
240
+ rank = NUM2INT(vrank);
241
+ mpipe_ary = rb_ivar_get(klass, id_allocated_mpipe);
242
+ mpipe = rb_ary_entry(mpipe_ary, rank);
243
+ if (NIL_P(mpipe)) {
244
+ mpipe = rb_class_new_instance(1, &vrank, klass);
245
+ rb_ary_store(mpipe_ary, rank, mpipe);
246
+ }
247
+ return mpipe;
248
+ }
249
+
250
+
251
+ #if 0
252
+ /*
253
+ * Returns +false+. Just for compatibility to IO.
254
+ */
255
+ static VALUE
256
+ mp_false(VALUE self)
257
+ {
258
+ MPipe(self);
259
+ return Qfalse;
260
+ }
261
+ #endif
262
+
263
+ /*
264
+ * Returns +nil+. Just for compatibility to IO.
265
+ */
266
+ static VALUE
267
+ mp_nil(VALUE self)
268
+ {
269
+ MPipe(self);
270
+ return Qnil;
271
+ }
272
+
273
+ #if 0
274
+ /*
275
+ * Returns *pipempi* itself. Just for compatibility to IO.
276
+ */
277
+ static VALUE
278
+ mp_self(VALUE self)
279
+ {
280
+ MPipe(self);
281
+ return self;
282
+ }
283
+
284
+ /*
285
+ * Returns 0. Just for compatibility to IO.
286
+ */
287
+ static VALUE
288
+ mp_0(VALUE self)
289
+ {
290
+ MPipe(self);
291
+ return INT2FIX(0);
292
+ }
293
+
294
+ /*
295
+ * Returns the argument unchanged. Just for compatibility to IO.
296
+ */
297
+ static VALUE
298
+ mp_first(VALUE self, VALUE arg)
299
+ {
300
+ MPipe(self);
301
+ return arg;
302
+ }
303
+
304
+ /*
305
+ * Raises NotImplementedError.
306
+ */
307
+ static VALUE
308
+ mp_unimpl(int argc, VALUE *argv, VALUE self)
309
+ {
310
+ MPipe(self);
311
+ rb_notimplement();
312
+
313
+ UNREACHABLE;
314
+ }
315
+ #endif
316
+
317
+ #define mp_close mp_nil
318
+
319
+ static VALUE
320
+ mp_write(VALUE self, VALUE str)
321
+ {
322
+ struct MPipe *ptr = MPipe(self);
323
+ int istat;
324
+ int pos, count;
325
+
326
+ str = StringValue(str);
327
+ pos = 0;
328
+
329
+ while (pos < RSTRING_LEN(str)) {
330
+ count = RSTRING_LEN(str) - pos;
331
+ if (count > mp_buffer_size) {
332
+ count = mp_buffer_size;
333
+ }
334
+ memcpy(ptr->send_buffer, RSTRING_PTR(str)+pos, count);
335
+
336
+ istat = MPI_Send(ptr->send_buffer, count, MPI_CHAR, ptr->rank,
337
+ 0, MPI_COMM_WORLD);
338
+ if (istat != MPI_SUCCESS) {
339
+ rb_raise(rb_eStandardError,"MPI_send failed with status=%d\n",istat);
340
+ }
341
+
342
+ pos += count;
343
+ }
344
+ return self;
345
+ }
346
+
347
+
348
+
349
+ static VALUE
350
+ mp_outbuf(char *buf, int len, VALUE outbuf)
351
+ {
352
+ if (NIL_P(outbuf)) {
353
+ return rb_str_new(buf, len);
354
+ } else {
355
+ rb_str_resize(outbuf, len);
356
+ MEMCPY(RSTRING_PTR(outbuf), buf, char, len);
357
+ return outbuf;
358
+ }
359
+ }
360
+
361
+ static VALUE
362
+ mp_substr(struct MPipe *ptr, VALUE maxlen, VALUE outbuf)
363
+ {
364
+ int max_len;
365
+ int count = ptr->recv_count;
366
+ char *recv_buf = ptr->recv_buffer + ptr->recv_begin;
367
+
368
+ if (!NIL_P(maxlen)) {
369
+ max_len = NUM2INT(maxlen);
370
+ if (max_len < 0) {
371
+ rb_raise(rb_eArgError, "negative length %d given", max_len);
372
+ }
373
+ if (max_len < count) {
374
+ ptr->recv_begin += max_len;
375
+ ptr->recv_count -= max_len;
376
+ return mp_outbuf(recv_buf, max_len, outbuf);
377
+ }
378
+ }
379
+ ptr->recv_begin = 0;
380
+ ptr->recv_count = 0;
381
+ return mp_outbuf(recv_buf, count, outbuf);
382
+ }
383
+
384
+
385
+ static VALUE
386
+ mp_read(int argc, VALUE *argv, VALUE self)
387
+ {
388
+ struct MPipe *ptr = MPipe(self);
389
+ MPI_Status status;
390
+ int istat;
391
+ int count;
392
+ VALUE maxlen = Qnil;
393
+ VALUE outbuf = Qnil;
394
+
395
+ rb_scan_args(argc, argv, "02", &maxlen, &outbuf);
396
+
397
+ if (ptr->recv_count > 0) {
398
+ return mp_substr(ptr, maxlen, outbuf);
399
+ }
400
+ if (ptr->recv_count == 0) {
401
+ istat = MPI_Recv(ptr->recv_buffer, mp_buffer_size, MPI_CHAR, ptr->rank,
402
+ 0, MPI_COMM_WORLD, &status);
403
+ if (istat != MPI_SUCCESS) {
404
+ rb_raise(rb_eStandardError,"MPI_recv failed with status=%d\n",istat);
405
+ }
406
+ } else { // requesting
407
+ istat = MPI_Wait(&ptr->recv_request, &status);
408
+ if (istat != MPI_SUCCESS) {
409
+ rb_raise(rb_eStandardError,"MPI_Wait failed with status=%d",istat);
410
+ }
411
+ }
412
+ MPI_Get_count(&status, MPI_CHAR, &count);
413
+ ptr->recv_count = count;
414
+ return mp_substr(ptr, maxlen, outbuf);
415
+ }
416
+
417
+
418
+
419
+ static void
420
+ request_irecv(struct MPipe *ptr)
421
+ {
422
+ int istat;
423
+
424
+ if (ptr->recv_count == 0) {
425
+ istat = MPI_Irecv(ptr->recv_buffer, mp_buffer_size, MPI_CHAR, ptr->rank,
426
+ 0, MPI_COMM_WORLD, &ptr->recv_request);
427
+ if (istat != MPI_SUCCESS) {
428
+ rb_raise(rb_eStandardError,"MPI_Irecv failed with status=%d",istat);
429
+ }
430
+ ptr->recv_count = -1; // requesting
431
+ }
432
+ }
433
+
434
+ /*
435
+ not requesting: recv_count=0
436
+ requesting: recv_count=-1
437
+ buffered: recv_count=n
438
+ */
439
+
440
+ /*
441
+ * call-seq:
442
+ * mpipe.read_nonblock(integer[, outbuf [, opts]]) -> string
443
+ *
444
+ * Similar to #read, but raises +EOFError+ at end of string unless the
445
+ * +exception: false+ option is passed in.
446
+ */
447
+ static VALUE
448
+ mp_read_nonblock(int argc, VALUE *argv, VALUE self)
449
+ {
450
+ struct MPipe *ptr = MPipe(self);
451
+ MPI_Status status;
452
+ int istat;
453
+ int count;
454
+ int complete = 0;
455
+ VALUE maxlen = Qnil;
456
+ VALUE outbuf = Qnil;
457
+ VALUE opts = Qnil;
458
+ VALUE val;
459
+
460
+ rb_scan_args(argc, argv, "02:", &maxlen, &outbuf, &opts);
461
+
462
+ if (ptr->recv_count > 0) {
463
+ return mp_substr(ptr, maxlen, outbuf);
464
+ }
465
+ request_irecv(ptr);
466
+ istat = MPI_Test(&ptr->recv_request, &complete, &status);
467
+ if (istat != MPI_SUCCESS) {
468
+ rb_raise(rb_eStandardError,"MPI_Test failed with status=%d",istat);
469
+ }
470
+ if (complete) {
471
+ MPI_Get_count(&status, MPI_CHAR, &count);
472
+ ptr->recv_count = count;
473
+ val = mp_substr(ptr, maxlen, outbuf);
474
+ } else {
475
+ if (!NIL_P(opts) &&
476
+ rb_hash_lookup2(opts, sym_exception, Qundef) == Qfalse) {
477
+ return Qnil;
478
+ } else {
479
+ rb_raise(eEAGAINWaitReadable,"MPI_Irecv would block");
480
+ }
481
+ }
482
+ return val;
483
+ }
484
+
485
+ static VALUE
486
+ mp_s_select(int argc, VALUE *argv, VALUE mod)
487
+ {
488
+ struct MPipe *ptr;
489
+ MPI_Request *ary_of_requests;
490
+ int *ary_of_indices;
491
+ MPI_Status *ary_of_statuses;
492
+ int incount, outcount;
493
+ int i, count, istat;
494
+ VALUE rd_ary, result_ary, item;
495
+
496
+ if (argc==0) {
497
+ rb_raise(rb_eArgError, "no argument");
498
+ }
499
+ incount = RARRAY_LEN(argv[0]);
500
+
501
+ result_ary = rb_ary_new();
502
+ rd_ary = rb_ary_new();
503
+ rb_ary_push(result_ary, rd_ary);
504
+ for (i=0; i < incount; i++) {
505
+ item = RARRAY_AREF(argv[0], i);
506
+ ptr = MPipe(item);
507
+ if (ptr->recv_count > 0) {
508
+ rb_ary_push(rd_ary, item);
509
+ }
510
+ }
511
+ if (RARRAY_LEN(rd_ary) > 0) {
512
+ return result_ary;
513
+ }
514
+
515
+ ary_of_requests = ALLOCA_N(MPI_Request, incount);
516
+ ary_of_statuses = ALLOCA_N(MPI_Status, incount);
517
+ ary_of_indices = ALLOCA_N(int, incount);
518
+
519
+ for (i=0; i < incount; i++) {
520
+ item = RARRAY_AREF(argv[0], i);
521
+ ptr = MPipe(item);
522
+ request_irecv(ptr);
523
+ ary_of_requests[i] = ptr->recv_request;
524
+ }
525
+
526
+ istat = MPI_Waitsome(incount, ary_of_requests,
527
+ &outcount, ary_of_indices, ary_of_statuses);
528
+ if (istat != MPI_SUCCESS) {
529
+ rb_raise(rb_eStandardError,"MPI_Waitany failed with status=%d",istat);
530
+ }
531
+
532
+ for (i=0; i < outcount; i++) {
533
+ item = RARRAY_AREF(argv[0], ary_of_indices[i]);
534
+ MPI_Get_count(&ary_of_statuses[i], MPI_BYTE, &count);
535
+ ptr = MPipe(item);
536
+ ptr->recv_count = count;
537
+ rb_ary_push(rd_ary, item);
538
+ }
539
+ return result_ary;
540
+ }
541
+
542
+
543
+ void Init_mpipe()
544
+ {
545
+ VALUE cMPipe, mComm;
546
+
547
+ cMPipe = rb_define_class("MPipe", rb_cData);
548
+
549
+ // MPI
550
+ rb_define_module_function(cMPipe, "init", mp_mpi_init, -1);
551
+ rb_define_module_function(cMPipe, "finalize", mp_mpi_finalize, 0);
552
+ rb_define_module_function(cMPipe, "abort", mp_mpi_abort, 1);
553
+ rb_define_module_function(cMPipe, "buffer_size", mp_mpi_buffer_size, 0);
554
+ rb_define_module_function(cMPipe, "buffer_size=", mp_mpi_set_buffer_size, 1);
555
+
556
+ rb_define_const(cMPipe, "VERSION", rb_str_new2(MPIPE_VERSION));
557
+ rb_define_const(cMPipe, "MPI_VERSION", INT2NUM(MPI_VERSION));
558
+ rb_define_const(cMPipe, "MPI_SUBVERSION", INT2NUM(MPI_SUBVERSION));
559
+ rb_define_const(cMPipe, "SUCCESS", INT2NUM(MPI_SUCCESS));
560
+ rb_define_const(cMPipe, "PROC_NULL", INT2NUM(MPI_PROC_NULL));
561
+
562
+ // MPI::Comm
563
+ mComm = rb_define_module_under(cMPipe, "Comm");
564
+ rb_define_module_function(mComm, "rank", mp_comm_rank, 0);
565
+ rb_define_module_function(mComm, "size", mp_comm_size, 0);
566
+
567
+ //rb_include_module(cMPipe, rb_mEnumerable);
568
+ rb_define_alloc_func(cMPipe, mp_s_allocate);
569
+ rb_define_singleton_method(cMPipe, "new", mp_s_new, 1);
570
+ rb_define_method(cMPipe, "initialize", mp_initialize, 1);
571
+
572
+ rb_define_method(cMPipe, "write", mp_write, 1);
573
+ rb_define_method(cMPipe, "write_nonblock", mp_write, 1);
574
+ rb_define_method(cMPipe, "print", mp_write, 1);
575
+ rb_define_method(cMPipe, "read", mp_read, -1);
576
+ rb_define_method(cMPipe, "read_nonblock", mp_read_nonblock, -1);
577
+ rb_define_method(cMPipe, "close", mp_close, 1);
578
+
579
+ rb_define_singleton_method(cMPipe, "select", mp_s_select, -1);
580
+
581
+ sym_exception = ID2SYM(rb_intern("exception"));
582
+ id_allocated_mpipe = rb_intern("allocated_mpipe");
583
+ eEAGAINWaitReadable = rb_const_get(rb_cIO, rb_intern("EWOULDBLOCKWaitReadable"));
584
+ }