fairy 0.6.0 → 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/Makefile +1 -0
  2. data/bin/fairy +35 -5
  3. data/ext/extconf.rb +3 -0
  4. data/ext/fairy.c +180 -0
  5. data/ext/fairy.h +94 -0
  6. data/ext/fiber_mon.h +32 -0
  7. data/ext/fixnum-buffer.c +483 -0
  8. data/ext/p-group-by.c +529 -0
  9. data/ext/p-xgroup-by.c +467 -0
  10. data/ext/simple-hash.c +44 -0
  11. data/ext/string-buffer.c +286 -0
  12. data/ext/xmarshaled-queue.c +699 -0
  13. data/ext/xsized-queue.c +528 -0
  14. data/ext/xthread.h +65 -0
  15. data/fairy.gemspec +5 -2
  16. data/lib/fairy.rb +10 -1
  17. data/lib/fairy/client/group-by.rb +57 -2
  18. data/lib/fairy/client/here.rb +2 -1
  19. data/lib/fairy/controller.rb +25 -4
  20. data/lib/fairy/master.rb +17 -3
  21. data/lib/fairy/master/c-basic-group-by.rb +4 -2
  22. data/lib/fairy/master/c-cat.rb +3 -2
  23. data/lib/fairy/master/c-direct-product.rb +5 -3
  24. data/lib/fairy/master/c-filter.rb +5 -3
  25. data/lib/fairy/master/c-group-by.rb +13 -0
  26. data/lib/fairy/master/c-junction.rb +3 -2
  27. data/lib/fairy/master/c-seg-join.rb +3 -1
  28. data/lib/fairy/master/c-seg-shuffle.rb +3 -2
  29. data/lib/fairy/master/c-seg-split.rb +1 -1
  30. data/lib/fairy/master/c-seg-zip.rb +3 -1
  31. data/lib/fairy/master/c-sort.rb +7 -2
  32. data/lib/fairy/master/c-wc.rb +5 -3
  33. data/lib/fairy/node.rb +13 -2
  34. data/lib/fairy/node/p-barrier.rb +1 -1
  35. data/lib/fairy/node/p-basic-group-by.rb +22 -12
  36. data/lib/fairy/node/p-direct-product.rb +4 -2
  37. data/lib/fairy/node/p-filter.rb +8 -7
  38. data/lib/fairy/node/p-find.rb +2 -1
  39. data/lib/fairy/node/p-group-by.rb +17 -6
  40. data/lib/fairy/node/p-inject.rb +3 -2
  41. data/lib/fairy/node/p-output-file.rb +1 -1
  42. data/lib/fairy/node/p-seg-join.rb +2 -1
  43. data/lib/fairy/node/p-seg-zip.rb +2 -1
  44. data/lib/fairy/node/p-single-exportable.rb +3 -1
  45. data/lib/fairy/node/p-sort.rb +4 -2
  46. data/lib/fairy/node/p-task.rb +1 -1
  47. data/lib/fairy/node/p-wc.rb +5 -2
  48. data/lib/fairy/processor.rb +25 -18
  49. data/lib/fairy/share/block-source.rb +12 -2
  50. data/lib/fairy/share/conf.rb +35 -5
  51. data/lib/fairy/share/hash-simple-hash.rb +1 -1
  52. data/lib/fairy/share/log.rb +11 -4
  53. data/lib/fairy/share/pool-dictionary.rb +2 -1
  54. data/lib/fairy/share/port-marshaled-queue.rb +8 -1
  55. data/lib/fairy/share/port.rb +55 -45
  56. data/lib/fairy/share/reference.rb +2 -1
  57. data/lib/fairy/share/varray.rb +3 -1
  58. data/lib/fairy/share/vfile.rb +4 -2
  59. data/lib/fairy/version.rb +1 -1
  60. data/sample/sort.rb +69 -3
  61. data/spec/fairy8_spec.rb +1 -1
  62. data/test/testc.rb +380 -2
  63. data/tools/cap_recipe/Capfile +3 -3
  64. data/tools/fairy_conf_wizard.rb +375 -0
  65. data/tools/fairy_perf_graph.rb +15 -3
  66. data/tools/git-tag +1 -0
  67. data/tools/log-analysis.rb +59 -11
  68. metadata +33 -34
  69. data/ext/simple_hash/extconf.rb +0 -4
  70. data/ext/simple_hash/simple_hash.c +0 -42
@@ -0,0 +1,528 @@
1
+ /**********************************************************************
2
+
3
+ xmarshaled_queue.c -
4
+ Copyright (C) 2007-2011 Rakuten, Inc.
5
+
6
+ **********************************************************************/
7
+
8
+ #include "ruby.h"
9
+
10
+ #include "xthread.h"
11
+ #include "fiber_mon.h"
12
+
13
+ #include "fairy.h"
14
+
15
+ extern VALUE rb_cXThreadMonitor;
16
+ extern VALUE rb_cFiberMon;
17
+
18
+ static VALUE rb_cFairyFastTempfile;
19
+
20
+ static VALUE SET_NO_IMPORT;
21
+
22
+ VALUE rb_cFairyXSizedQueue;
23
+
24
+ #define xsq(name) fairy_xsized_queue##name
25
+ #define rb_xsq(name) rb_fairy_xsized_queue##name
26
+
27
+ typedef struct rb_xsq(_struct)
28
+ {
29
+ long chunk_size;
30
+ long min_chunk_no;
31
+ long queues_limit;
32
+
33
+ char use_string_buffer_p;
34
+
35
+ VALUE push_queue;
36
+ VALUE push_cv;
37
+
38
+ VALUE queues;
39
+ VALUE queues_mon;
40
+
41
+ VALUE pop_queue;
42
+ VALUE pop_cv;
43
+
44
+ VALUE (*queue_push)(VALUE, VALUE);
45
+
46
+ VALUE (*mon_synchronize)();
47
+ VALUE (*cv_wait)();
48
+ VALUE (*cv_signal)();
49
+ VALUE (*cv_broadcast)();
50
+
51
+ } xsq(_t);
52
+
53
+ #define GetFairyXSizedQueuePtr(obj, tobj) \
54
+ TypedData_Get_Struct((obj), xsq(_t), &xsq(_data_type), (tobj))
55
+
56
+ static void
57
+ xsq(_mark)(void *ptr)
58
+ {
59
+ xsq(_t) *sq = (xsq(_t)*)ptr;
60
+
61
+ rb_gc_mark(sq->push_queue);
62
+ rb_gc_mark(sq->push_cv);
63
+ rb_gc_mark(sq->queues);
64
+ rb_gc_mark(sq->queues_mon);
65
+ rb_gc_mark(sq->pop_queue);
66
+ rb_gc_mark(sq->pop_cv);
67
+ }
68
+
69
+ static void
70
+ xsq(_free)(void *ptr)
71
+ {
72
+ ruby_xfree(ptr);
73
+ }
74
+
75
+ static size_t
76
+ xsq(_memsize)(const void *ptr)
77
+ {
78
+ return ptr ? sizeof(xsq(_t)) : 0;
79
+ }
80
+
81
+ #ifdef HAVE_RB_DATA_TYPE_T_FUNCTION
82
+ static const rb_data_type_t xsq(_data_type) = {
83
+ "fairy_xsized_queue",
84
+ {xsq(_mark), xsq(_free), xsq(_memsize),},
85
+ };
86
+ #else
87
+ static const rb_data_type_t xsq(_data_type) = {
88
+ "fairy_xsized_queue",
89
+ xsq(_mark),
90
+ xsq(_free),
91
+ xsq(_memsize),
92
+ };
93
+ #endif
94
+
95
+ static VALUE
96
+ xsq(_alloc)(VALUE klass)
97
+ {
98
+ VALUE volatile obj;
99
+ xsq(_t) *sq;
100
+
101
+ obj = TypedData_Make_Struct(klass, xsq(_t), &xsq(_data_type), sq);
102
+
103
+ sq->chunk_size = 0;
104
+ sq->min_chunk_no = 0;
105
+ sq->queues_limit = 0;
106
+
107
+ sq->push_queue = Qnil;
108
+ sq->push_cv = Qnil;
109
+
110
+ sq->queues = Qnil;
111
+ sq->queues_mon = Qnil;
112
+
113
+ sq->pop_queue = Qnil;
114
+ sq->pop_cv = Qnil;
115
+
116
+ sq->queue_push = NULL;
117
+
118
+ sq->mon_synchronize = NULL;
119
+ sq->cv_wait = NULL;
120
+ sq->cv_broadcast = NULL;
121
+
122
+ return obj;
123
+ }
124
+
125
+ static VALUE rb_xsq(_monitor_cond_wait)(VALUE);
126
+ static VALUE rb_xsq(_genmon_synchronize)(VALUE, VALUE (*)(VALUE), VALUE);
127
+ static VALUE rb_xsq(_gencond_wait)(VALUE);
128
+ static VALUE rb_xsq(_gencond_broadcast)(VALUE);
129
+ static VALUE rb_xsq(_gencond_signal)(VALUE);
130
+
131
+ static VALUE rb_xsq(_empty_push)(VALUE, VALUE);
132
+ static VALUE rb_xsq(_str_push)(VALUE, VALUE);
133
+ static VALUE rb_xsq(_obj_push)(VALUE, VALUE);
134
+
135
+ static VALUE
136
+ rb_xsq(_initialize)(VALUE self, VALUE policy, VALUE queues_mon, VALUE pop_cv)
137
+ {
138
+ VALUE sz;
139
+ VALUE flag;
140
+ VALUE dir;
141
+ xsq(_t) *sq;
142
+
143
+ GetFairyXSizedQueuePtr(self, sq);
144
+
145
+ sz = rb_fairy_conf("XSIZED_QUEUE_CHUNK_SIZE", policy, "chunk_size");
146
+ sq->chunk_size = NUM2LONG(sz);
147
+
148
+ sz = rb_fairy_conf("XSIZED_QUEUE_QUEUES_LIMIT",
149
+ policy, "queues_limit");
150
+ sq->queues_limit = NUM2LONG(sz);
151
+
152
+ flag = rb_fairy_conf("XSIZED_QUEUE_USE_STRING_BUFFER",
153
+ policy, "use_string_buffer");
154
+ sq->use_string_buffer_p = RTEST(flag);
155
+
156
+ sq->queues = rb_xthread_fifo_new();
157
+ if (NIL_P(queues_mon)) {
158
+ queues_mon = rb_xthread_monitor_new();
159
+ }
160
+ sq->queues_mon = queues_mon;
161
+
162
+ sq->push_queue = Qnil;
163
+ sq->push_cv = rb_funcall(queues_mon, rb_intern("new_cond"), 0);
164
+
165
+ if (NIL_P(pop_cv)) {
166
+ pop_cv = rb_funcall(queues_mon, rb_intern("new_cond"), 0);
167
+ }
168
+ sq->pop_cv = pop_cv;
169
+ sq->pop_queue = Qnil;
170
+
171
+ sq->queue_push = rb_xsq(_empty_push);
172
+
173
+ if (CLASS_OF(sq->queues_mon) == rb_cXThreadMonitor) {
174
+ sq->mon_synchronize = rb_xthread_monitor_synchronize;
175
+ sq->cv_wait = rb_xsq(_monitor_cond_wait);
176
+ sq->cv_broadcast = rb_xthread_monitor_cond_broadcast;
177
+ sq->cv_signal = rb_xthread_monitor_cond_signal;
178
+ }
179
+ else if (CLASS_OF(sq->queues_mon) == rb_cFiberMonMonitor) {
180
+ sq->mon_synchronize = rb_fibermon_monitor_synchronize;
181
+ sq->cv_wait = rb_fibermon_cond_wait;
182
+ sq->cv_signal = rb_fibermon_cond_signal;
183
+ sq->cv_broadcast = rb_fibermon_cond_broadcast;
184
+ }
185
+ else {
186
+ sq->mon_synchronize = rb_xsq(_genmon_synchronize);
187
+ sq->cv_wait = rb_xsq(_gencond_wait);
188
+ sq->cv_signal = rb_xsq(_gencond_signal);
189
+ sq->cv_broadcast = rb_xsq(_gencond_broadcast);
190
+ }
191
+
192
+ return self;
193
+ }
194
+
195
+ static VALUE
196
+ rb_xsq(_monitor_cond_wait)(VALUE arg)
197
+ {
198
+ return rb_xthread_monitor_cond_wait(arg, Qnil);
199
+ }
200
+
201
+ static VALUE
202
+ rb_xsq(_genmon_synchronize)(VALUE arg1, VALUE (*arg2)(VALUE), VALUE arg3)
203
+ {
204
+ static ID id_synchronize;
205
+ if (!id_synchronize) id_synchronize = rb_intern("synchronize");
206
+
207
+ return rb_funcall(arg1, id_synchronize, 2, arg2, arg3);
208
+ }
209
+
210
+ static VALUE
211
+ rb_xsq(_gencond_wait)(VALUE arg)
212
+ {
213
+ static ID id_wait;
214
+ if (!id_wait) id_wait = rb_intern("wait");
215
+
216
+ return rb_funcall(arg, id_wait, 1, Qnil);
217
+ }
218
+
219
+ static VALUE
220
+ rb_xsq(_gencond_signal)(VALUE arg1)
221
+ {
222
+ static ID id_signal;
223
+ if (!id_signal) id_signal = rb_intern("signal");
224
+
225
+ return rb_funcall(arg1, id_signal, 0);
226
+ }
227
+
228
+ static VALUE
229
+ rb_xsq(_gencond_broadcast)(VALUE arg1)
230
+ {
231
+ static ID id_broadcast;
232
+ if (!id_broadcast) id_broadcast = rb_intern("broadcast");
233
+
234
+ return rb_funcall(arg1, id_broadcast, 0);
235
+ }
236
+
237
+
238
+ static VALUE
239
+ xsq(_initialize)(int argc, VALUE *argv, VALUE self)
240
+ {
241
+ VALUE policy;
242
+ VALUE queues_mon;
243
+ VALUE pop_cv;
244
+
245
+ rb_scan_args(argc, argv, "12", &policy, &queues_mon, &pop_cv);
246
+ return rb_xsq(_initialize)(self, policy, queues_mon, pop_cv);
247
+ }
248
+
249
+ VALUE
250
+ rb_xsq(_new)(VALUE policy, VALUE queues_mon, VALUE pop_cv)
251
+ {
252
+ VALUE self;
253
+
254
+ self = xsq(_alloc)(rb_cFairyXSizedQueue);
255
+ rb_xsq(_initialize)(self, policy, queues_mon, pop_cv);
256
+ return self;
257
+ }
258
+
259
+ static VALUE rb_xsq(_queues_push)(VALUE, VALUE);
260
+ static VALUE rb_xsq(_broadcast)(VALUE);
261
+ static VALUE rb_xsq(_store)(VALUE, VALUE);
262
+ static VALUE rb_xsq(_restore)(VALUE, VALUE);
263
+
264
+ VALUE
265
+ rb_xsq(_push)(VALUE self, VALUE e)
266
+ {
267
+ xsq(_t) *sq;
268
+
269
+ GetFairyXSizedQueuePtr(self, sq);
270
+ return sq->queue_push(self, e);
271
+ }
272
+
273
+ static VALUE
274
+ rb_xsq(_empty_push)(VALUE self, VALUE e)
275
+ {
276
+ xsq(_t) *sq;
277
+ GetFairyXSizedQueuePtr(self, sq);
278
+
279
+ if (EOS_P(e)) {
280
+ rb_xthread_fifo_push(sq->queues, e);
281
+ return self;
282
+ }
283
+
284
+ if (sq->use_string_buffer_p && CLASS_OF(e) == rb_cString) {
285
+ sq->push_queue = rb_fairy_string_buffer_new();
286
+ sq->queue_push = rb_xsq(_str_push);
287
+ }
288
+ else {
289
+ sq->push_queue = rb_ary_new2(sq->min_chunk_no);
290
+ sq->queue_push = rb_xsq(_obj_push);
291
+ }
292
+ return sq->queue_push(self, e);
293
+ }
294
+
295
+ static VALUE
296
+ rb_xsq(_obj_push)(VALUE self, VALUE e)
297
+ {
298
+ xsq(_t) *sq;
299
+ GetFairyXSizedQueuePtr(self, sq);
300
+
301
+ if (EOS_P(e)) {
302
+ rb_xsq(_queues_push)(self, sq->push_queue);
303
+ sq->push_queue = Qnil;
304
+ rb_xsq(_queues_push)(self, e);
305
+ return self;
306
+ }
307
+
308
+ if (sq->use_string_buffer_p && CLASS_OF(e) == rb_cString) {
309
+ rb_xsq(_queues_push)(self, sq->push_queue);
310
+ sq->push_queue = Qnil;
311
+ sq->queue_push = rb_xsq(_empty_push);
312
+ return sq->queue_push(self, e);
313
+ }
314
+
315
+ rb_ary_push(sq->push_queue, e);
316
+ if (RARRAY_LEN(sq->push_queue) >= sq->chunk_size || e == SET_NO_IMPORT) {
317
+ rb_xsq(_queues_push)(self, sq->push_queue);
318
+ sq->push_queue = Qnil;
319
+ sq->queue_push = rb_xsq(_empty_push);
320
+ }
321
+ return self;
322
+ }
323
+
324
+ static VALUE
325
+ rb_xsq(_str_push)(VALUE self, VALUE e)
326
+ {
327
+ xsq(_t) *sq;
328
+
329
+ GetFairyXSizedQueuePtr(self, sq);
330
+ if (EOS_P(e)) {
331
+ rb_xsq(_queues_push)(self, sq->push_queue);
332
+ rb_xsq(_queues_push)(self, e);
333
+ return self;
334
+ }
335
+
336
+ if (CLASS_OF(e) != rb_cString) {
337
+ rb_xsq(_queues_push)(self, sq->push_queue);
338
+ sq->push_queue = Qnil;
339
+ sq->queue_push = rb_xsq(_empty_push);
340
+ }
341
+ rb_fairy_string_buffer_push(sq->push_queue, e);
342
+ if (NUM2LONG(rb_fairy_string_buffer_size(sq->push_queue)) >= sq->chunk_size) {
343
+ rb_xsq(_queues_push)(self, sq->push_queue);
344
+ sq->push_queue = Qnil;
345
+ sq->queue_push = rb_xsq(_empty_push);
346
+ }
347
+ return self;
348
+ }
349
+
350
+ static VALUE
351
+ rb_xsq(_push_raw)(VALUE self, VALUE raw)
352
+ {
353
+ xsq(_t) *sq;
354
+
355
+ GetFairyXSizedQueuePtr(self, sq);
356
+
357
+ if (!NIL_P(sq->push_queue)) {
358
+ rb_xsq(_queues_push)(self, sq->push_queue);
359
+ sq->push_queue = Qnil;
360
+ }
361
+ rb_xsq(_queues_push)(self, raw);
362
+
363
+ return self;
364
+ }
365
+
366
+ struct rb_xsq(_queues_push_arg)
367
+ {
368
+ VALUE self;
369
+ VALUE buf;
370
+ };
371
+
372
+ static VALUE rb_xsq(_push_sync)(struct rb_xsq(_queues_push_arg) *);
373
+
374
+ static VALUE
375
+ rb_xsq(_queues_push)(VALUE self, VALUE buf)
376
+ {
377
+ xsq(_t) *sq;
378
+ struct rb_xsq(_queues_push_arg) arg;
379
+
380
+ GetFairyXSizedQueuePtr(self, sq);
381
+
382
+ arg.self = self;
383
+ arg.buf = buf;
384
+
385
+ sq->mon_synchronize(sq->queues_mon,
386
+ rb_xsq(_push_sync), &arg);
387
+ }
388
+
389
+ static VALUE
390
+ rb_xsq(_push_sync)(struct rb_xsq(_queues_push_arg) *arg)
391
+ {
392
+ xsq(_t) *sq;
393
+ GetFairyXSizedQueuePtr(arg->self, sq);
394
+
395
+ if (NUM2LONG(rb_xthread_fifo_length(sq->queues)) > sq->queues_limit) {
396
+ while(NUM2LONG(rb_xthread_fifo_length(sq->queues)) > sq->queues_limit) {
397
+ sq->cv_wait(sq->push_cv);
398
+ }
399
+ }
400
+
401
+ rb_xthread_fifo_push(sq->queues, arg->buf);
402
+ sq->cv_broadcast(sq->pop_cv);
403
+ return arg->self;
404
+ }
405
+
406
+ struct rb_xsq(_pop_arg)
407
+ {
408
+ VALUE self;
409
+ VALUE buf;
410
+ };
411
+
412
+ static VALUE rb_xsq(_pop_wait)(struct rb_xsq(_pop_arg) *arg);
413
+
414
+ VALUE
415
+ rb_xsq(_pop)(VALUE self)
416
+ {
417
+ xsq(_t) *sq;
418
+ VALUE buf;
419
+ struct rb_xsq(_pop_arg) arg;
420
+ GetFairyXSizedQueuePtr(self, sq);
421
+
422
+ while (NIL_P(sq->pop_queue) || RARRAY_LEN(sq->pop_queue) == 0) {
423
+ {
424
+ arg.self = self;
425
+ arg.buf = Qnil;
426
+ sq->mon_synchronize(sq->queues_mon,
427
+ rb_xsq(_pop_wait), &arg);
428
+ buf = arg.buf;
429
+ }
430
+
431
+ if (EOS_P(buf)) {
432
+ sq->pop_queue = rb_ary_new3(1, buf);
433
+ }
434
+ else {
435
+ if (CLASS_OF(buf) == rb_cString) {
436
+ buf = rb_marshal_load(buf);
437
+ }
438
+ if (CLASS_OF(buf) == rb_cFairyStringBuffer) {
439
+ sq->pop_queue = rb_fairy_string_buffer_to_a(buf);
440
+ }
441
+ else {
442
+ sq->pop_queue = buf;
443
+ }
444
+ }
445
+ }
446
+ return rb_ary_shift(sq->pop_queue);
447
+ }
448
+
449
+ static VALUE
450
+ rb_xsq(_pop_wait)(struct rb_xsq(_pop_arg) *arg)
451
+ {
452
+ VALUE self = arg->self;
453
+ xsq(_t) *sq;
454
+ VALUE buf = Qnil;
455
+
456
+ GetFairyXSizedQueuePtr(self, sq);
457
+
458
+ buf = rb_xthread_fifo_pop(sq->queues);
459
+ while (NIL_P(buf)) {
460
+ sq->cv_wait(sq->pop_cv);
461
+ buf = rb_xthread_fifo_pop(sq->queues);
462
+ }
463
+ sq->cv_signal(sq->push_cv);
464
+ arg->buf = buf;
465
+ return arg->self;
466
+ }
467
+
468
+ VALUE
469
+ rb_xsq(_pop_raw)(VALUE self)
470
+ {
471
+ xsq(_t) *sq;
472
+ VALUE pop_raw = Qnil;
473
+ VALUE buf;
474
+ struct rb_xsq(_pop_arg) arg;
475
+
476
+ GetFairyXSizedQueuePtr(self, sq);
477
+ {
478
+ arg.self = self;
479
+ arg.buf = Qnil;
480
+ sq->mon_synchronize(sq->queues_mon,
481
+ rb_xsq(_pop_wait), &arg);
482
+ buf = arg.buf;
483
+ }
484
+ return buf;
485
+ }
486
+
487
+ VALUE
488
+ rb_xsq(_inspect)(VALUE self)
489
+ {
490
+ VALUE str;
491
+ xsq(_t) *sq;
492
+
493
+ GetFairyXSizedQueuePtr(self, sq);
494
+
495
+ str = rb_sprintf("<%s:%p chunk_size=%d, min_chunk_no=%d, queues_limit=%d use_string_bffer_p=%d>",
496
+ rb_obj_classname(self),
497
+ (void*)self,
498
+ sq->chunk_size,
499
+ sq->min_chunk_no,
500
+ sq->queues_limit,
501
+ sq->use_string_buffer_p);
502
+ return str;
503
+ }
504
+
505
+
506
+ void
507
+ Init_xsized_queue()
508
+ {
509
+ VALUE xsq;
510
+
511
+ rb_cFairyFastTempfile = rb_const_get(rb_mFairy, rb_intern("FastTempfile"));
512
+
513
+
514
+ SET_NO_IMPORT = rb_const_get(rb_cFairyImport, rb_intern("SET_NO_IMPORT"));
515
+
516
+ rb_cFairyXSizedQueue = rb_define_class_under(rb_mFairy, "XSizedQueue", rb_cObject);
517
+
518
+ xsq = rb_cFairyXSizedQueue;
519
+
520
+ rb_define_alloc_func(xsq, xsq(_alloc));
521
+ rb_define_method(xsq, "initialize", xsq(_initialize), -1);
522
+ rb_define_method(xsq, "push", rb_xsq(_push), 1);
523
+ rb_define_method(xsq, "push_raw", rb_xsq(_push_raw), 1);
524
+ rb_define_method(xsq, "pop", rb_xsq(_pop), 0);
525
+ rb_define_method(xsq, "pop_raw", rb_xsq(_pop_raw), 0);
526
+ rb_define_method(xsq, "inspect", rb_xsq(_inspect), 0);
527
+ }
528
+