YkLib 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.
Files changed (125) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +6 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +7 -0
  7. data/Gemfile.lock +34 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +44 -0
  10. data/Rakefile +6 -0
  11. data/YkLib.gemspec +29 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/lib/YkLib/Yk/__advance__.rb +151 -0
  15. data/lib/YkLib/Yk/__defun__.rb +44 -0
  16. data/lib/YkLib/Yk/__hook__.rb +244 -0
  17. data/lib/YkLib/Yk/__minmax__.rb +123 -0
  18. data/lib/YkLib/Yk/__stdlog.rb +329 -0
  19. data/lib/YkLib/Yk/adhocLiterals/email.rb +119 -0
  20. data/lib/YkLib/Yk/adhocLiterals/path.rb +402 -0
  21. data/lib/YkLib/Yk/adhocLiterals/tag.rb +19 -0
  22. data/lib/YkLib/Yk/adhocLiterals/url.rb +36 -0
  23. data/lib/YkLib/Yk/adhocLiterals.rb +199 -0
  24. data/lib/YkLib/Yk/auto_escseq.rb +5 -0
  25. data/lib/YkLib/Yk/auto_pstore.rb +179 -0
  26. data/lib/YkLib/Yk/bsearch.rb +120 -0
  27. data/lib/YkLib/Yk/clambda.rb +309 -0
  28. data/lib/YkLib/Yk/confLine.rb +423 -0
  29. data/lib/YkLib/Yk/create_tty_width_available.rb +24 -0
  30. data/lib/YkLib/Yk/crypt.rb +26 -0
  31. data/lib/YkLib/Yk/debug2 +1 -0
  32. data/lib/YkLib/Yk/debug2.rb +473 -0
  33. data/lib/YkLib/Yk/debugout.rb +139 -0
  34. data/lib/YkLib/Yk/email_tz.rb +533 -0
  35. data/lib/YkLib/Yk/enum_expect.rb +170 -0
  36. data/lib/YkLib/Yk/errlog.rb +5 -0
  37. data/lib/YkLib/Yk/escseq.rb +59 -0
  38. data/lib/YkLib/Yk/eval_alt.rb +281 -0
  39. data/lib/YkLib/Yk/expector.rb +93 -0
  40. data/lib/YkLib/Yk/fetch.rb +556 -0
  41. data/lib/YkLib/Yk/fetch_old.rb +290 -0
  42. data/lib/YkLib/Yk/fib.rb +158 -0
  43. data/lib/YkLib/Yk/file_aux.rb +843 -0
  44. data/lib/YkLib/Yk/file_aux2.rb +919 -0
  45. data/lib/YkLib/Yk/file_aux_old.rb +160 -0
  46. data/lib/YkLib/Yk/filemod.rb +19 -0
  47. data/lib/YkLib/Yk/force_escseq.rb +3 -0
  48. data/lib/YkLib/Yk/generator__.rb +144 -0
  49. data/lib/YkLib/Yk/generator__.rb.org +139 -0
  50. data/lib/YkLib/Yk/indenter/argless_case.rb +46 -0
  51. data/lib/YkLib/Yk/indenter/each_token.rb +671 -0
  52. data/lib/YkLib/Yk/indenter/free_case.rb +313 -0
  53. data/lib/YkLib/Yk/indenter/if_less.rb +53 -0
  54. data/lib/YkLib/Yk/indenter/independent_ensure.rb +23 -0
  55. data/lib/YkLib/Yk/indenter/independent_rescue.rb +23 -0
  56. data/lib/YkLib/Yk/indenter/operand_circumflex.rb +0 -0
  57. data/lib/YkLib/Yk/indenter/operand_period.rb +16 -0
  58. data/lib/YkLib/Yk/indenter/parenless_and.rb +37 -0
  59. data/lib/YkLib/Yk/indenter/post_test.rb +48 -0
  60. data/lib/YkLib/Yk/indenter/token.rb +1525 -0
  61. data/lib/YkLib/Yk/indenter.rb +1382 -0
  62. data/lib/YkLib/Yk/inot.rb +265 -0
  63. data/lib/YkLib/Yk/intf.rb +815 -0
  64. data/lib/YkLib/Yk/io_aux.rb +1332 -0
  65. data/lib/YkLib/Yk/ioctl.rb +60 -0
  66. data/lib/YkLib/Yk/ipcc.rb +87 -0
  67. data/lib/YkLib/Yk/ipcountry.rb +207 -0
  68. data/lib/YkLib/Yk/ipv4adr.rb +318 -0
  69. data/lib/YkLib/Yk/localmail.rb +276 -0
  70. data/lib/YkLib/Yk/method_chain.rb +359 -0
  71. data/lib/YkLib/Yk/misc_tz.rb +1716 -0
  72. data/lib/YkLib/Yk/missing_method.rb +50 -0
  73. data/lib/YkLib/Yk/mojiConv.rb +257 -0
  74. data/lib/YkLib/Yk/nostdlog.rb +4 -0
  75. data/lib/YkLib/Yk/on_marshal.rb +20 -0
  76. data/lib/YkLib/Yk/overrider.rb +47 -0
  77. data/lib/YkLib/Yk/path.rb +293 -0
  78. data/lib/YkLib/Yk/path_aux.rb +883 -0
  79. data/lib/YkLib/Yk/path_aux_alt.rb +0 -0
  80. data/lib/YkLib/Yk/path_rep.rb +1267 -0
  81. data/lib/YkLib/Yk/pg_setup.rb +917 -0
  82. data/lib/YkLib/Yk/procinfo.rb +314 -0
  83. data/lib/YkLib/Yk/proclist.rb +492 -0
  84. data/lib/YkLib/Yk/property.rb +863 -0
  85. data/lib/YkLib/Yk/ranger.rb +606 -0
  86. data/lib/YkLib/Yk/resolv_tz.rb +88 -0
  87. data/lib/YkLib/Yk/rlprompt.rb +73 -0
  88. data/lib/YkLib/Yk/rootexec.rb +48 -0
  89. data/lib/YkLib/Yk/rpm-packageproxy.rb +784 -0
  90. data/lib/YkLib/Yk/rpm-packageproxy2.rb +1430 -0
  91. data/lib/YkLib/Yk/rwhen.rb +21 -0
  92. data/lib/YkLib/Yk/selector.rb +124 -0
  93. data/lib/YkLib/Yk/set.rb +170 -0
  94. data/lib/YkLib/Yk/shellquote.rb +300 -0
  95. data/lib/YkLib/Yk/sio.rb +1001 -0
  96. data/lib/YkLib/Yk/sio0.rb +835 -0
  97. data/lib/YkLib/Yk/sio_aux.rb +1524 -0
  98. data/lib/YkLib/Yk/sio_inot.rb +86 -0
  99. data/lib/YkLib/Yk/sock_aux.rb +42 -0
  100. data/lib/YkLib/Yk/spipe.rb +843 -0
  101. data/lib/YkLib/Yk/sql_table.rb +565 -0
  102. data/lib/YkLib/Yk/stdlog.rb +4 -0
  103. data/lib/YkLib/Yk/syscommand.rb +173 -0
  104. data/lib/YkLib/Yk/sysinit.rb +75 -0
  105. data/lib/YkLib/Yk/ttyFontWidth.rb +46113 -0
  106. data/lib/YkLib/Yk/tty_char.dump +0 -0
  107. data/lib/YkLib/Yk/tty_char.rb +47 -0
  108. data/lib/YkLib/Yk/tty_char_create.rb +437031 -0
  109. data/lib/YkLib/Yk/tty_char_static.rb +437016 -0
  110. data/lib/YkLib/Yk/tty_rewrite.rb +142 -0
  111. data/lib/YkLib/Yk/tty_str.rb +461 -0
  112. data/lib/YkLib/Yk/tty_width.dat.rb +114 -0
  113. data/lib/YkLib/Yk/tty_width.rb +180 -0
  114. data/lib/YkLib/Yk/tty_width_available +569 -0
  115. data/lib/YkLib/Yk/tty_width_list +0 -0
  116. data/lib/YkLib/Yk/tty_width_list.linux +280 -0
  117. data/lib/YkLib/Yk/tty_width_list.windows +324 -0
  118. data/lib/YkLib/Yk/tz_tty +0 -0
  119. data/lib/YkLib/Yk/tz_tty.rb +0 -0
  120. data/lib/YkLib/Yk/uprepos.rb +94 -0
  121. data/lib/YkLib/Yk/userinfo.rb +91 -0
  122. data/lib/YkLib/Yk/with.rb +109 -0
  123. data/lib/YkLib/version.rb +3 -0
  124. data/lib/YkLib.rb +6 -0
  125. metadata +170 -0
@@ -0,0 +1,1524 @@
1
+ require 'Yk/path_aux'
2
+ require 'set'
3
+
4
+ #p > nil
5
+
6
+
7
+ class IO
8
+ BUFF_SZ = 1024 * 1024
9
+
10
+ def use_select # use time interrupt for normal file reading
11
+ @_use_select = true
12
+ end
13
+ def dont_use_select
14
+ @_use_select = false
15
+ end
16
+ class << self
17
+ def _open path, mode = "r", **opt
18
+ begin
19
+ fd = sysopen path, self::NONBLOCK
20
+ io = for_fd(fd, **opt)
21
+ yield io
22
+ ensure
23
+ io.close if io
24
+ end
25
+ end
26
+
27
+ def _openw path, mode = "w", offset = nil, **opt
28
+ flg = offset ? TRUNC : 0
29
+ begin
30
+ fd = sysopen path, self::WRONLY|self::NONBLOCK|self::CREAT|flg
31
+ io = for_fd(fd, **opt)
32
+ io.seek offset if offset
33
+ yield io
34
+ ensure
35
+ io.close if io
36
+ end
37
+ end
38
+
39
+ def _src path
40
+ if !path.is_a? IO
41
+ fr = _open path do |io|
42
+ yield io
43
+ end
44
+ else
45
+ yield io
46
+ end
47
+ end
48
+ def _dst path
49
+ if !path.is_a? IO
50
+ fr = _openw path do |io|
51
+ yield io
52
+ end
53
+ else
54
+ yield io
55
+ end
56
+ end
57
+
58
+ def binread path, length = nil, offset = 0
59
+ _open path, "br" do |io|
60
+ if _use_select? io
61
+ io.seek offset
62
+ buff = ""
63
+ while !length || buff.bytesize < length
64
+ Fiber.select io, :read
65
+ readBuff = ""
66
+ begin
67
+ io.read_nonblock(length - buff.bytesize, readBuff)
68
+ rescue EOFError
69
+ break
70
+ else
71
+ buff += readBuff
72
+ end
73
+ end
74
+ else
75
+ io.seek offset
76
+ return io._org_read(length)
77
+ end
78
+ end
79
+ end
80
+
81
+ def binwrite path, buff, offset = nil
82
+ _openw path, "bw", offset do |io|
83
+ if _use_select? io
84
+ length = buff.bytesize
85
+ while wsize < length
86
+ Fiber.select io, :write
87
+ readBuff = ""
88
+ wsize += io.write_nonblock(buff.byteslice(wsize, length - wsize))
89
+ end
90
+ else
91
+ io._org_write buff
92
+ end
93
+ end
94
+ end
95
+
96
+ def copy_stream src, dst, copy_length = nil, src_offset = nil
97
+ _src path do |fr|
98
+ fr.seek scr_offset if src_offset
99
+ if fr._use_select?
100
+ _dst path do |fw|
101
+ if fw._use_select?
102
+ cpsz = BUFF_SZ
103
+ if copy_length
104
+ if copy_length < cpsz
105
+ cpsz = copy_length
106
+ end
107
+ readBuff = fr._flush_residue
108
+ copied = 0
109
+ while copied < copy_length
110
+ Fiber.select fr, :read
111
+ begin
112
+ csz = [copy_length - copied, cpsz].min
113
+ fr.read_nonblock(csz, readBuff)
114
+ rsz = readBuff.bytesize
115
+ wsz = 0
116
+ while wsz < rsz
117
+ Fiber.select fw, :write
118
+ wsz += fw.write_nonblock(readBuff.byteslice(wsz, rsz - wsz))
119
+ end
120
+ rescue EOFError
121
+ break
122
+ else
123
+ copied += wsz
124
+ end
125
+ end
126
+ else
127
+ loop do
128
+ Fiber.select fr, :read
129
+ begin
130
+ fr.read_nonblock(BUFF_SZ, readBuff)
131
+ rsz = readBuff.bytesize
132
+ wsz = 0
133
+ while wsz < rsz
134
+ Fiber.select fw, :write
135
+ wsz += fw.write_nonblock(readBuff.byteslice(wsz, rsz - wsz))
136
+ end
137
+ rescue EOFError
138
+ break
139
+ end
140
+ end
141
+ end
142
+ else
143
+ cpsz = BUFF_SZ
144
+ if copy_length
145
+ if copy_length < cpsz
146
+ cpsz = copy_length
147
+ end
148
+ readBuff = ""
149
+ copied = 0
150
+ while copied < copy_length
151
+ Fiber.select fr, :read
152
+ begin
153
+ csz = [copy_length - copied, cpsz].min
154
+ fr.read_nonblock(csz, readBuff)
155
+ fw._org_write(readBuff)
156
+ copied += readBuff.bytesize
157
+ rescue EOFError
158
+ break
159
+ end
160
+ end
161
+ else
162
+ loop do
163
+ Fiber.select fr, :read
164
+ begin
165
+ fr.read_nonblock(BUFF_SZ, readBuff)
166
+ fw._org_write(readBuff)
167
+ rescue EOFError
168
+ break
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
+ else
175
+ _dst path do |fw|
176
+ if fw._use_select?
177
+ cpsz = BUFF_SZ
178
+ readBuff = fr._org_read(copy_length)
179
+ rsz = readBuff.bytesize
180
+ wsz = 0
181
+ while wsz < rsz
182
+ Fiber.select fw, :write
183
+ wsz += fw.write_nonblock(readBuff.byteslice(wsz, rsz - wsz))
184
+ end
185
+ else
186
+ cpsz = BUFF_SZ
187
+ readBuff = fr._org_read(copy_length)
188
+ fw._org_write(readBuff)
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
194
+
195
+ alias_method :_org_foreach, :foreach
196
+ def foreach path, rs = $/, chomp: false, **opt, &bl
197
+ body = ->y{
198
+ readBuff = ""
199
+ lstC = rs != "" ? rs : $/ * 2
200
+ ret = true
201
+ _open path, **opt do |io|
202
+ ret = nil
203
+ if io._use_select?
204
+ left = nil
205
+ begin
206
+ loop do
207
+ Fiber.select io, :read
208
+ io.read_nonblock(BUF_SZ, readBuff)
209
+ readBuff = left + readBuff if left
210
+ readBuff.each_line rs do |ln|
211
+ if ln.byteslice(-lstC.bytesize..-1) == lstC
212
+ y.call chomp ? ln.byteslice(0...-lstC.bytesize) : ln
213
+ left = nil
214
+ else
215
+ left = ln
216
+ end
217
+ end
218
+ end
219
+ rescue EOFError
220
+ y.call left if left
221
+ end
222
+ else
223
+ io._org_each_line rs, chomp: chomp do |ln|
224
+ y.call ln
225
+ end
226
+ end
227
+ end
228
+ ret
229
+ }
230
+ if bl
231
+ body.call ->{ bl[_1] }
232
+ else
233
+ return Enumerator.new do |x|
234
+ body.call ->{ x << _1 }
235
+ end
236
+ end
237
+ end
238
+
239
+
240
+ alias_method :_org_read, :read
241
+ def read path, length = nil, offset = 0, **opt
242
+ _open path, **opt do |io|
243
+ io.seek offset if offset != 0
244
+ if io._use_select?
245
+ res = ""
246
+ readBuff = ""
247
+ begin
248
+ if length
249
+ while res.bytesize < length
250
+ Fiber.select io, :read
251
+ io.read_nonblock(length, readBuff)
252
+ res += readBuff
253
+ end
254
+ else
255
+ loop do
256
+ Fiber.select io, :read
257
+ io.read_nonblock(BUFF_SZ, readBuff)
258
+ res += readBuff
259
+ end
260
+ end
261
+ rescue EOFError
262
+ return res
263
+ end
264
+ else
265
+ return io._org_read length
266
+ end
267
+ end
268
+ end
269
+
270
+ alias_method :_org_readlines, :readlines
271
+ def readlines path, *ag, chomp: false, **opts
272
+ _open path, **opt do |io|
273
+ return io.readlines *ag, chomp: chomp
274
+ end
275
+ end
276
+
277
+ alias_method :_org_write, :write
278
+ def write path, buff, offset = nil, **opt
279
+ _openw path, offset, **opt do |io|
280
+ if io._use_select?
281
+ wsz = 0
282
+ while wsz < buff.bytesize
283
+ Fiber.select fw, :write
284
+ wsz += fw.write_nonblock(buff.byteslice(wsz, buff.bytesize - wsz))
285
+ end
286
+ else
287
+ io._org_write buff
288
+ end
289
+ end
290
+ end
291
+ end
292
+
293
+ #private
294
+ def __fiber__
295
+ @__fiber__
296
+ end
297
+ def __fiber__= f
298
+ @__fiber__ = f
299
+ end
300
+ def _use_select?
301
+ if @_use_select == nil && ![STDERR, STDIN, STDOUT].include?(self)
302
+ begin
303
+ _org_pos
304
+ rescue Errno::ESPIPE
305
+ @_use_select = true
306
+ else
307
+ @_use_select = false
308
+ end
309
+ end
310
+ @_use_select
311
+ end
312
+
313
+ def _flush_residue
314
+ @_residue or (
315
+ @_residue = nil;
316
+ ""
317
+ )
318
+ end
319
+
320
+ public
321
+ alias_method :_org_operator_put, :<<
322
+ def << buff
323
+ if _use_select?
324
+ Fiber.select self, :write
325
+ if !buff.is_a? String
326
+ buff = buff.to_s
327
+ end
328
+ wsz = 0
329
+ while wsz < buff.bytesize
330
+ Fiber.select self, :write
331
+ wsz += write_nonblock(buff.byteslice(wsz, buff.bytesize - wsz))
332
+ end
333
+ self
334
+ else
335
+ _org_operator_put buff
336
+ end
337
+ end
338
+
339
+ alias _org_each_byte each_byte
340
+ def each_byte &bl
341
+ if _use_select?
342
+ body = ->y{
343
+ begin
344
+ readBuff = _flush_residue
345
+ loop do
346
+ readBuff.each_byte do |ch|
347
+ y.call ch
348
+ end
349
+ Fiber.select self, :read
350
+ read_nonblock(BUF_SZ, readBuff)
351
+ end
352
+ rescue EOFError
353
+ end
354
+ }
355
+ if bl
356
+ body.call ->{ bl[_1] }
357
+ else
358
+ return Enumerator.new do |x|
359
+ body.call ->{ x << _1 }
360
+ end
361
+ end
362
+ else
363
+ _org_each_byte &bl
364
+ end
365
+ end
366
+
367
+ alias _org_each_char each_char
368
+ def each_char &bl
369
+ if _use_select?
370
+ body = ->y{
371
+ begin
372
+ readBuff = _flush_residue
373
+ left = nil
374
+ resFirst = readBuff.bytesize == 0
375
+ loop do
376
+ if resFirst
377
+ loop do
378
+ Fiber.select self, :read
379
+ read_nonblock(BUF_SZ, readBuff)
380
+ next if readBuff.size == 0
381
+ readBuff = left + readBuff if left
382
+ resFirst = false
383
+ break
384
+ end
385
+ end
386
+ i = 0
387
+ sz = readBuff.bytesize
388
+ lastChars = []
389
+ readBuff.each_char do |c|
390
+ if sz - i < 4
391
+ lastChars.push [c != c.scrub, c]
392
+ else
393
+ y.call c
394
+ end
395
+ i += c.bytesize
396
+ end
397
+ left = ""
398
+ i = j = 0
399
+ norm = false
400
+ lastChars.reverse_each do |e|
401
+ j += e[1].bytesize
402
+ if !norm && e[0]
403
+ i += e[1].bytesize
404
+ else
405
+ norm = true
406
+ end
407
+ end
408
+ if i == 0
409
+ left = nil
410
+ readBuff.byteslice(-j...-1).each_char do |c|
411
+ y.call c
412
+ end
413
+ else
414
+ left = readBuff.byteslice(-i..-1)
415
+ readBuff.byteslice(-j...-i).each_char do |c|
416
+ y.call c
417
+ end
418
+ end
419
+ end
420
+ rescue EOFError
421
+ left.each_char do |c|
422
+ y.call c
423
+ end
424
+ end
425
+ }
426
+ if bl
427
+ body.call ->{ bl[_1] }
428
+ else
429
+ return Enumerator.new do |x|
430
+ body.call ->{ x << _1 }
431
+ end
432
+ end
433
+ else
434
+ _org_each_char &bl
435
+ end
436
+ end
437
+
438
+ alias _org_each_codepoint each_codepoint
439
+ def each_codepoint &bl
440
+ if _use_select?
441
+ body = ->y{
442
+ each_char do |c|
443
+ y.call c.codepoints[0]
444
+ end
445
+ }
446
+ if bl
447
+ body.call ->{ bl[_1] }
448
+ else
449
+ return Enumerator.new do |x|
450
+ body.call ->{ x << _1 }
451
+ end
452
+ end
453
+ else
454
+ _org_each_codepoint &bl
455
+ end
456
+ end
457
+
458
+ alias _org_each each
459
+ alias _org_each_line each_line
460
+ def each_line rs = $/, chomp: false, &bl
461
+ if _use_select?
462
+ body = ->y{
463
+ readBuff = _flush_residue
464
+ lstC = rs != "" ? rs : $/ * 2
465
+ rsz = BUF_SZ
466
+ left = nil
467
+ resFirst = readBuff.bytesize > 0
468
+ begin
469
+ loop do
470
+ if resFirst
471
+ Fiber.select self, :read
472
+ read_nonblock(rsz, readBuff)
473
+ readBuff = left + readBuff if left
474
+ resFirst = false
475
+ end
476
+ readBuff.each_line rs do |ln|
477
+ if ln.byteslice(-lstC.bytesize..-1) == lstC
478
+ y.call chomp ? ln.byteslice(0...-lstC.bytesize) : ln
479
+ left = nil
480
+ else
481
+ left = ln
482
+ end
483
+ end
484
+ end
485
+ rescue EOFError
486
+ y.call left if left
487
+ end
488
+ }
489
+ if bl
490
+ body.call ->{ bl[_1] }
491
+ else
492
+ return Enumerator.new do |x|
493
+ body.call ->{ x << _1 }
494
+ end
495
+ end
496
+ else
497
+ _org_each_line rs, chomp: chomp, &bl
498
+ end
499
+ end
500
+ alias each each_line
501
+
502
+ alias _org_getbyte getbyte
503
+ def getbyte
504
+ if _use_select?
505
+ if @_residue
506
+ case @_residue.bytesize
507
+ when 0
508
+ @_residue = nil
509
+ when 1
510
+ ret = @_residue.ord
511
+ @_residue = nil
512
+ return ret
513
+ else
514
+ ret = @_residue.byteslice(0..0).ord
515
+ @_residue = @_residue.byteslice(1..-1)
516
+ return ret
517
+ end
518
+ end
519
+ begin
520
+ loop do
521
+ Fiber.select self, :read
522
+ rb = ""
523
+ read_nonblock(1, rb)
524
+ if rb.bytesize == 1
525
+ return rb.ord
526
+ end
527
+ end
528
+ rescue EOFError
529
+ return nil
530
+ end
531
+ else
532
+ _org_getbyte
533
+ end
534
+ end
535
+
536
+ alias _org_getc getc
537
+ def getc
538
+ begin
539
+ readchar
540
+ rescue EOFError
541
+ return nil
542
+ end
543
+ end
544
+
545
+ alias _org_gets gets
546
+ def gets *ag, chomp: false, **opts
547
+ begin
548
+ readline *ag, chomp: chomp, **opts
549
+ rescue EOFError
550
+ nil
551
+ end
552
+ end
553
+
554
+ alias _org_read read
555
+ def read length = nil, outbuf = ""
556
+ if _use_select?
557
+ outbuf.replace _flush_residue
558
+ readBuff = ""
559
+ begin
560
+ if length
561
+ while res.bytesize < length
562
+ Fiber.select self, :read
563
+ read_nonblock(length - res.bytesize, readBuff)
564
+ res += readBuff
565
+ end
566
+ if (ls = res.bytesize - length) > 0
567
+ @_residue = res.byteslice(-ls .. -1)
568
+ end
569
+ else
570
+ loop do
571
+ Fiber.select self, :read
572
+ read_nonblock(BUFF_SZ, readBuff)
573
+ res += readBuff
574
+ end
575
+ end
576
+ rescue EOFError
577
+ end
578
+ return res
579
+ else
580
+ _org_read length, outbuf
581
+ end
582
+ end
583
+
584
+ alias _org_readbyte readbyte
585
+ def readbyte
586
+ if _use_select?
587
+ if @_residue
588
+ if @_residue.bytesize > 0
589
+ ret = @_residue.byteslice(1).ord
590
+ @_residue = @_residue.byteslice(2..-1)
591
+ if @_residue.bytesize == 0
592
+ @_residue = nil
593
+ end
594
+ return ret
595
+ else
596
+ @_residue = nil
597
+ end
598
+ end
599
+ readBuff = ""
600
+ loop do
601
+ Fiber.select self, :read
602
+ read_nonblock(1, readBuff)
603
+ if readBuff.size > 0
604
+ return readBuff[0].ord
605
+ end
606
+ end
607
+ else
608
+ _org_readbyte
609
+ end
610
+ end
611
+
612
+ alias _org_readchar readchar
613
+ def readchar
614
+ if _use_select?
615
+ buff = _flush_residue
616
+ (1..).each do |i|
617
+ if i > buff.bytesize
618
+ loop do
619
+ readBuff = ""
620
+ Fiber.select self, :read
621
+ read_nonblock(1, readBuff)
622
+ if readBuff.size > 0
623
+ buff += readBuff
624
+ break
625
+ end
626
+ end
627
+ end
628
+ c = buff.byteslice(0, i)
629
+ if c == (cscr = c.scrub) # normal char
630
+ @_residue = buff.byteslice(i..-1)
631
+ return c
632
+ elsif c.byteslice(-1..-1) == cscr.byteslice(-1..-1) # abnormal char before normal char
633
+ @_residue = buff.byteslice(2..-1)
634
+ return buff.byteslice(1) # flush abnormal char, first
635
+ end
636
+ end
637
+ else
638
+ _org_readchar
639
+ end
640
+ end
641
+
642
+ alias _org_readline readline
643
+ def readline *ag, chomp: false, **opts
644
+ if _use_select?
645
+ limit = ag[0]._?{_1.is_a?(Integer)} || ag[1]._?{_1.is_a?(Integer)}
646
+ rs = ag[0]._?{_1.is_a?(String)} || ag[1]._?{_1.is_a?(String)} || $/
647
+ lstC = rs != "" ? rs : $/ * 2
648
+ res = []
649
+ rsz = limit ? [BUF_SZ, limit].min : BUF_SZ
650
+ readBuff = _flush_residue
651
+ left = nil
652
+ begin
653
+ getln = ->{
654
+ readBuff = left + readBuff if left
655
+ readBuff.each_line rs do |ln|
656
+ if ln.byteslice(-lstC.bytesize..-1) == lstC
657
+ ret = chomp ? ln.byteslice(0...-lstC.bytesize) : ln
658
+ @_residue = readBuff.byteslice(ln.bytesize .. -1)
659
+ @_residue = nil if @_residue.bytesize == 0
660
+ return ret
661
+ else
662
+ left = ln
663
+ break
664
+ end
665
+ end
666
+ }
667
+ readSz = readBuff.bytesize
668
+ getln.call if readSz > 0
669
+ if limit
670
+ while readSz < limit
671
+ Fiber.select self, :read
672
+ read_nonblock([rsz, limit - readSz].min, readBuff)
673
+ readSz += readBuff.bytesize
674
+ getln.call
675
+ end
676
+ else
677
+ loop do
678
+ Fiber.select self, :read
679
+ read_nonblock(rsz, readBuff)
680
+ getln.call
681
+ end
682
+ end
683
+ rescue EOFError => err
684
+ return left if left
685
+ raise err
686
+ end
687
+ else
688
+ _org_readline *ag, chomp: chomp, **opts
689
+ end
690
+ end
691
+
692
+ alias _org_readlines readlines
693
+ def readlines *ag, chomp: false, **opts
694
+ if _use_select?
695
+ limit = ag[0]._?{_1.is_a?(Integer)} || ag[1]._?{_1.is_a?(Integer)}
696
+ rs = ag[0]._?{_1.is_a?(String)} || ag[1]._?{_1.is_a?(String)} || $/
697
+ readBuff = ""
698
+ lstC = rs != "" ? rs : $/ * 2
699
+ res = []
700
+ rsz = limit ? [BUF_SZ, limit].min : BUF_SZ
701
+ left = nil
702
+ begin
703
+ push_each = ->{
704
+ readBuff = left + readBuff if left
705
+ readBuff.each_line rs do |ln|
706
+ if ln.byteslice(-lstC.bytesize..-1) == lstC
707
+ res.push chomp ? ln.byteslice(0...-lstC.bytesize) : ln
708
+ left = nil
709
+ else
710
+ left = ln
711
+ end
712
+ end
713
+ }
714
+ if limit
715
+ readSz = 0
716
+ while readSz < limit
717
+ Fiber.select self, :read
718
+ read_nonblock([rsz, limit - readSz].min, readBuff)
719
+ readSz += readBuff.bytesize
720
+ push_each[]
721
+ end
722
+ else
723
+ loop do
724
+ Fiber.select self, :read
725
+ read_nonblock(rsz, readBuff)
726
+ push_each[]
727
+ end
728
+ end
729
+ rescue EOFError
730
+ res.push left if left
731
+ end
732
+ else
733
+ res = _org_readlines *ag, chomp: chomp
734
+ end
735
+ res
736
+ end
737
+
738
+ alias _org_ungetbyte ungetbyte
739
+ def ungetbyte ag
740
+ if _use_select?
741
+ if ag.is_a?(Integer) && 0 <= ag && ag <= 255
742
+ @_residue += ag.chr
743
+ elsif ag.is_a? String
744
+ @_residue += ag
745
+ else
746
+ raise ArgumentError.new("ungetbyte(ag = '#{ag.inspect}') failed, because ag is neither String nor Integer(0..255).")
747
+ end
748
+ else
749
+ _org_ungetbyte ag
750
+ end
751
+ end
752
+
753
+ alias _org_ungetc ungetc
754
+ def ungetc ag
755
+ if _use_select?
756
+ case ag
757
+ when Integer
758
+ @_residue += ag.chr
759
+ when String
760
+ @_residue += ag
761
+ end
762
+ else
763
+ _org_ungetc ag
764
+ end
765
+ end
766
+
767
+ alias _tell_pos tell
768
+ def tell
769
+ if _use_select?
770
+ _tell_pos - @_residue.bytesize
771
+ else
772
+ _tell_pos
773
+ end
774
+ end
775
+
776
+ alias _org_pos pos
777
+ def pos
778
+ if _use_select?
779
+ _org_pos - @_residue.bytesize
780
+ else
781
+ _org_pos
782
+ end
783
+ end
784
+
785
+ alias _org_pos= pos=
786
+ def pos= arg
787
+ ret = (_org_pos = arg)
788
+ if _use_select?
789
+ @_residue = nil
790
+ end
791
+ ret
792
+ end
793
+
794
+ alias _org_seek seek
795
+ def seek *args
796
+ ret = _org_seek *args
797
+ if _use_select?
798
+ @_residue = nil
799
+ end
800
+ ret
801
+ end
802
+
803
+
804
+ alias _org_print print
805
+ def print *args
806
+ if _use_select?
807
+ buff = args.map(&:to_s).inject(&:+)
808
+ wsz = 0
809
+ while wsz < buff.bytesize
810
+ Fiber.select self, :write
811
+ wsz += write_nonblock(buff.byteslice(wsz, buff.bytesize - wsz))
812
+ end
813
+ else
814
+ _org_print *args
815
+ end
816
+ end
817
+
818
+
819
+ alias _org_printf printf
820
+ def printf *args
821
+ if _use_select?
822
+ buff = sprintf *args
823
+ wsz = 0
824
+ while wsz < buff.bytesize
825
+ Fiber.select self, :write
826
+ wsz += write_nonblock(buff.byteslice(wsz, buff.bytesize - wsz))
827
+ end
828
+ else
829
+ _org_print *args
830
+ end
831
+ end
832
+
833
+ alias _org_putc putc
834
+ def putc c
835
+ if _use_select?
836
+ buff = (case c
837
+ when Integer
838
+ (c % 256).chr
839
+ when String
840
+ c[0]
841
+ else
842
+ (c.to_i % 256).chr
843
+ end)
844
+ wsz = 0
845
+ while wsz < buff.bytesize
846
+ Fiber.select self, :write
847
+ wsz += write_nonblock(buff.byteslice(wsz, buff.bytesize - wsz))
848
+ end
849
+ else
850
+ _org_putc *args
851
+ end
852
+ end
853
+
854
+
855
+ alias _org_puts puts
856
+ def puts *args
857
+ if _use_select?
858
+ require 'stringio'
859
+ sio = Stringio.new "", "w"
860
+ sio.puts *args
861
+ buff = sio.string
862
+ wsz = 0
863
+ while wsz < buff.bytesize
864
+ Fiber.select self, :write
865
+ wsz += write_nonblock(buff.byteslice(wsz, buff.bytesize - wsz))
866
+ end
867
+ else
868
+ _org_puts *args
869
+ end
870
+ end
871
+
872
+
873
+ alias _org_write write
874
+ def write *args
875
+ if _use_select?
876
+ buff = args.map(&:to_s).inject(&:+)
877
+ wsz = 0
878
+ while wsz < buff.bytesize
879
+ p
880
+ Fiber.select self, :write
881
+ p
882
+ wsz += write_nonblock(buff.byteslice(wsz, buff.bytesize - wsz))
883
+ end
884
+ else
885
+ _org_write *args
886
+ end
887
+ end
888
+
889
+ perm = Proc.new do |*args|
890
+ ret = []
891
+ (args.length).downto 1 do |i|
892
+ args.permutation(i) do |j|
893
+ ret.push j
894
+ end
895
+ end
896
+ ret += [""]
897
+ ret.join("|")
898
+ end
899
+ RWAMODE_REG = /w(#{perm['\+', '[tb]', 'x']})|[ra](#{perm['\+', '[tb]']})/
900
+
901
+ alias _org_reopen reopen
902
+ def reopen *args
903
+ ret = nil
904
+ case args
905
+ in [IO => io, *mode]
906
+ ret = _org_reopen io, *mode
907
+ in [path, *mode]
908
+ m = mode[0]
909
+ case m
910
+ when Integer, nil
911
+ m = (m || fcntl(Fcntl::F_GETFL, 0)) | NONBLOCK
912
+ else
913
+ if !defined? FMode
914
+ sm = m.to_s
915
+ if sm =~ /:/
916
+ smf = $`
917
+ enc = ":" + $'
918
+ else
919
+ smf = sm
920
+ enc = ""
921
+ end
922
+ m = 0
923
+ if smf =~ RWAMODE_REG
924
+ m = (case $&[0] + ($&["+"] || "")
925
+ when "r"
926
+ File::RDONLY
927
+ when "w"
928
+ File::WRONLY|File::CREAT|File::TRUNC
929
+ when "a"
930
+ File::WRONLY|File::CREAT|File::APPEND
931
+ when "r+"
932
+ File::RDWR
933
+ when "w+"
934
+ File::RDWR|File::CREAT|File::TRUNC
935
+ when "a+"
936
+ File::RDWR|File::CREAT|File::APPEND
937
+ end)
938
+ end
939
+ m |= NONBLOCK
940
+ elsif !m.is_a? FMode
941
+ fm = FMode.new(sm)
942
+ else
943
+ fm = m
944
+ end
945
+ end
946
+ if !fm
947
+ sma = sm ? [sm] : []
948
+ fd = self.class.sysopen path, m
949
+ begin
950
+ io = self.class.for_fd(fd, *sma)
951
+ ret = _org_reopen io
952
+ ensure
953
+ io.close
954
+ end
955
+ else
956
+ fm.nonblock = true
957
+ File.open path, fm do |fp|
958
+ ret = _org_reopen fp
959
+ end
960
+ end
961
+ end
962
+ @_use_select = nil
963
+ @_residue = nil
964
+ ret
965
+ end
966
+
967
+ end
968
+
969
+ class File
970
+ alias _org_flock flock
971
+ def flock mode
972
+ r, w = self.class.pipe
973
+ begin
974
+ Thread.new do
975
+ _org_flock mode
976
+ w._org_write "\n"
977
+ end
978
+ Fiber.select r, :read
979
+ r.read(1)
980
+ rescue
981
+ r.close
982
+ w.close
983
+ end
984
+ end
985
+ end
986
+
987
+ require 'socket'
988
+ class TCPServer
989
+ alias _org_accept accept
990
+ def accept
991
+ if _use_select?
992
+ Fiber.select self, :read
993
+ end
994
+ _org_accept
995
+ end
996
+ end
997
+
998
+ require 'fiber'
999
+
1000
+ using Friend
1001
+
1002
+ class Fiber
1003
+
1004
+ friend IO
1005
+
1006
+ class OrderedQueue < Array
1007
+ def initialize &prc
1008
+ @ev = prc
1009
+ end
1010
+ alias :_insert_at :insert
1011
+ def _insert item, bg = 0, ed = size
1012
+ if @ev.call(bg) == @ev.call(ed - 1)
1013
+ _insert ed - 1, item
1014
+ else
1015
+ if ed - bg == 1
1016
+ _insert_at ed, item
1017
+ elsif ed - bg == 2
1018
+ _insert_at ed - 1, item
1019
+ else
1020
+ m = (bg + ed).div 2
1021
+ if @ev.call(item) < @ev.call(self[m])
1022
+ _insert item, bg, m + 1
1023
+ elsif @ev.call(self[m + 1]) <= @ev.call(item)
1024
+ _insert item, m + 1, ed
1025
+ else
1026
+ _insert_at m + 1, item
1027
+ end
1028
+ end
1029
+ end
1030
+ end
1031
+ def insert item
1032
+ if size == 0
1033
+ push item
1034
+ else
1035
+ if @ev.call(self[0]) > @ev.call(item)
1036
+ unshift item
1037
+ elsif @ev.call(self[-1]) <= @ev.call(item)
1038
+ push item
1039
+ else
1040
+ _insert item
1041
+ end
1042
+ end
1043
+ end
1044
+ end
1045
+
1046
+ class Terminate < Exception
1047
+ end
1048
+
1049
+ attr_reader :mode, :io, :timeout, :token, :preceeded, :fiber
1050
+ List = Hash.new{|h, k| h[k] = Set.new}
1051
+
1052
+ class << self
1053
+ def fork *modes, &prc # mode : true, execute block first
1054
+ p
1055
+ fi = modes.index :first
1056
+ li = modes.index :late
1057
+ if !li
1058
+ first = true
1059
+ elsif !fi
1060
+ first = false
1061
+ elsif fi > li
1062
+ first = true
1063
+ else
1064
+ first = false
1065
+ end
1066
+ auto_cleanup = modes.include?(:auto_cleanup) ? :auto_cleanup : nil
1067
+ p prc
1068
+ fb = new do
1069
+ begin
1070
+ begin
1071
+ p :yellow
1072
+ prc.call
1073
+ p :cyan
1074
+ rescue Fiber::Terminate
1075
+ p :red
1076
+ # rescue Exception => ex
1077
+ # p :blue
1078
+ # p ex
1079
+ #ex.instance_eval {
1080
+ # ::STDERR.write "#{backtrace[0]}:#{ex} (#{self.class})".ln
1081
+ # backtrace[1..-1].each do |e|
1082
+ # ::STDERR.write(" " + e.ln)
1083
+ # end
1084
+ #}
1085
+ # p
1086
+ # @aborted = true
1087
+ #abort
1088
+ # raise
1089
+ end
1090
+ ensure
1091
+ current.delete
1092
+ end
1093
+ p :blue
1094
+ doSelect #never retrun
1095
+ end
1096
+ forked = fb.set_params first ? :start : :pass, auto_cleanup
1097
+ p current
1098
+ doSelect
1099
+ #end
1100
+ p forked
1101
+ forked
1102
+ end
1103
+
1104
+ #private
1105
+
1106
+ friend IO, Fiber
1107
+ def select_it *args
1108
+ self.current.set_params *args
1109
+ if doSelect == :terminate
1110
+ raise Terminate.new
1111
+ end
1112
+ end
1113
+ def select io, mode, timeout = nil
1114
+ io.__fiber__ = current
1115
+ select_it mode, io, timeout
1116
+ end
1117
+
1118
+ def doSelect
1119
+ wios = []
1120
+ rios = []
1121
+ active_fibers = []
1122
+ hasTimer = false
1123
+ list.reject{!_1.alive?}
1124
+ list.each do |fiber|
1125
+ if fiber.timeout
1126
+ hasTimer = true
1127
+ break
1128
+ end
1129
+ end
1130
+ now = Time.now if hasTimer
1131
+ tmout, passFiber = nil
1132
+ tmoutList = []
1133
+ list.each do |fiber|
1134
+ p fiber.selected?, fiber.mode, fiber.preceeded
1135
+ next if fiber.preceeded
1136
+ case fiber.selected? || fiber.mode
1137
+ when :read, :write
1138
+ if fiber.mode == :read
1139
+ rios.push fiber.io
1140
+ else # :write
1141
+ wios.push fiber.io
1142
+ end
1143
+ if fiber.timeout
1144
+ if !tmout || (tmout != 0 and tmout > fiber.timeout - now and tmoutList.clear)
1145
+ tmout = fiber.timeout - now
1146
+ tmout = 0 if tmout < 0
1147
+ end
1148
+ end
1149
+ when :timer
1150
+ if !tmout
1151
+ tmout = fiber.timeout - now
1152
+ tmout = 0 if tmout < 0
1153
+ tmoutList.push fiber
1154
+ elsif tmout == 0 && fiber.timeout - now <= 0
1155
+ tmoutList.push fiber
1156
+ elsif tmout == fiber.timeout - now
1157
+ tmoutList.push fiber
1158
+ elsif tmout > fiber.timeout - now
1159
+ tmout = fiber.timeout - now
1160
+ tmout = 0 if tmout < 0
1161
+ tmoutList.clear
1162
+ tmoutList.push fiber
1163
+ end
1164
+ when :stop
1165
+ # do nothing
1166
+ when :terminate, :start, true
1167
+ if !tmout
1168
+ tmout = 0
1169
+ tmoutList.push fiber
1170
+ elsif tmout == 0
1171
+ tmoutList.push fiber
1172
+ else
1173
+ tmout = 0
1174
+ tmoutList.clear
1175
+ tmoutList.push fiber
1176
+ end
1177
+ when :pass
1178
+ passFiber = fiber
1179
+ fiber.set_params :start
1180
+ else # token
1181
+ # do nothing
1182
+ end
1183
+ end
1184
+ p tmout
1185
+ p current
1186
+ p [rios, wios, tmoutList]
1187
+ if rios.size + wios.size + tmoutList.size == 0
1188
+ p
1189
+ if passFiber
1190
+ p passFiber
1191
+ tmoutList.push passFiber
1192
+ else
1193
+ p
1194
+ raise Exception.new("no selectable Fiber")
1195
+ end
1196
+ end
1197
+ p
1198
+ selectedList, srios, swios, seios = nil
1199
+ if ((!tmout && rios.size + wios.size > 0) || (tmout && tmout != 0))
1200
+ p
1201
+ begin
1202
+ p tmout, wios, rios
1203
+ srios, swios, seios = IO.select rios, wios, rios + wios, tmout
1204
+ rescue Errno::EINTR
1205
+ retry
1206
+ end
1207
+ now = nil
1208
+ timeouted = (!srios || srios.size == 0) && (!swios || swios.size == 0)
1209
+ [[rios, srios], [wios, swios]].each do |ios, sios|
1210
+ ios.each do |io|
1211
+ e = io.__fiber__
1212
+ if (sios && sios.include?(io)) || (e.timeout && e.timeout < (now ||= Time.now))
1213
+ e.set_selected
1214
+ (selectedList ||= []).push e
1215
+ end
1216
+ end
1217
+ end
1218
+ else #tmout = 0
1219
+ p
1220
+ timeouted = true
1221
+ end
1222
+ p srios
1223
+ p swios
1224
+ p seios
1225
+ p selectedList
1226
+ p tmoutList
1227
+ if timeouted
1228
+ (selectedList ||= []).push *tmoutList
1229
+ end
1230
+ current_fiber = selectedList.shuffle[0]
1231
+ current_fiber.reset_selected if current_fiber.selected?
1232
+ p current_fiber
1233
+ current_fiber.continue
1234
+ end
1235
+ def list
1236
+ List[Thread.current]
1237
+ end
1238
+
1239
+ public
1240
+
1241
+ def pass
1242
+ select_it :pass
1243
+ end
1244
+ def sleep t = :stop
1245
+ p :purple
1246
+ select_it t
1247
+ p :purple
1248
+ end
1249
+ def stopBy token, timeout = :stop
1250
+ res = select_it token, timeout
1251
+ if res == :start
1252
+ :timeout
1253
+ else
1254
+ token
1255
+ end
1256
+ end
1257
+ def awakeBy token
1258
+ list.each do |fiber|
1259
+ if fiber.token == token
1260
+ fiber.set_params :start
1261
+ end
1262
+ end
1263
+ select_it :start
1264
+ end
1265
+ def timer t
1266
+ loop do
1267
+ yield
1268
+ sleep t
1269
+ end
1270
+ end
1271
+ def waitall
1272
+ p.red
1273
+ while list.size > 1
1274
+ p.red list
1275
+ doSelect
1276
+ end
1277
+ p.red
1278
+ if list.to_a[0] != Fiber.current
1279
+ raise Exception.new("Unknown Exception : last fiber is not current fiber")
1280
+ end
1281
+ end
1282
+ end
1283
+
1284
+ #private
1285
+ def check_initialized
1286
+ if !self.class.list.include? self
1287
+ self.class.list.add self
1288
+ if block_given?
1289
+ yield
1290
+ end
1291
+ @mutexStack ||= []
1292
+ @lockStat ||= []
1293
+ @mutexList ||= Hash.new{|h, k| h[k] = 0}
1294
+ @preceeded ||= false
1295
+ end
1296
+ self
1297
+ end
1298
+ def delete
1299
+ self.class.list.delete self
1300
+ end
1301
+ def set_params *args
1302
+ check_initialized
1303
+ @mode, @timeout, @io, @token, @selected = nil
1304
+ args.each do |e|
1305
+ case e
1306
+ when :auto_cleanup
1307
+ @auto_cleanup = true
1308
+ when Symbol
1309
+ @mode = e
1310
+ when Time
1311
+ @timeout = e
1312
+ when Numeric
1313
+ @timeout = Time.now + e
1314
+ when IO
1315
+ @io = e
1316
+ when nil
1317
+ else
1318
+ @token = e
1319
+ end
1320
+ end
1321
+ @timeout and @mode ||= :timer
1322
+ self
1323
+ end
1324
+
1325
+ at_exit do
1326
+ Fiber.current.delete
1327
+ end
1328
+
1329
+ def auto_cleanup?
1330
+ @auto_cleanup
1331
+ end
1332
+ def set_awake
1333
+ set_params :start
1334
+ end
1335
+ def set_preceeded
1336
+ @preceeded = true
1337
+ end
1338
+ def reset_preceeded
1339
+ @preceeded = false
1340
+ end
1341
+ def set_selected
1342
+ @selected = true
1343
+ end
1344
+ def reset_selected
1345
+ @selected = false
1346
+ end
1347
+ def selected?
1348
+ return @selected
1349
+ end
1350
+ def continue arg = nil
1351
+ @mutexStack.each do |e|
1352
+ if e.has_semi_lock_fiber self
1353
+ e.lock self
1354
+ end
1355
+ end
1356
+ m = arg || @mode
1357
+ @mode, @timeout, @token = nil
1358
+ if Fiber.current != self
1359
+ p.bgGreen Fiber.current.mode, Fiber.current, self, btrace[0..3]
1360
+ if Fiber.current.mode == nil
1361
+ Fiber.current.set_params :start
1362
+ end
1363
+ transfer m
1364
+ else
1365
+ p.bgGreen self, :continue, btrace[0..3]
1366
+ end
1367
+ end
1368
+
1369
+ public
1370
+ def awake_at t = 0
1371
+ set_params t
1372
+ end
1373
+ def terminate
1374
+ if Fiber.current == self
1375
+ raise Terminate.new
1376
+ end
1377
+ set_params :terminate
1378
+ Fiber.select_it :pass
1379
+ end
1380
+ def awake
1381
+ set_params :start
1382
+ Fiber.select_it :pass
1383
+ end
1384
+
1385
+ class Mutex
1386
+ #private
1387
+ def initialize
1388
+ @stopped = {}
1389
+ @semi_lock_fibers = Hash.new{|h, k| h[k] = 0}
1390
+ @waiting_fibers = Hash.new
1391
+ end
1392
+ def lock fiber
1393
+ while @fiber && @fiber != fiber
1394
+ @waiting_fibers[fiber] = true
1395
+ Fiber.sleep
1396
+ end
1397
+ @fiber = fiber
1398
+ @semi_lock_fibers.keys.each do |e|
1399
+ if e != fiber
1400
+ e.set_preceeded
1401
+ end
1402
+ end
1403
+ @fiber.reset_preceeded
1404
+ end
1405
+ def unlock fiber
1406
+ if @fiber == fiber
1407
+ @semi_lock_fibers.keys.each do |e|
1408
+ if e != self
1409
+ e.reset_preceeded
1410
+ end
1411
+ end
1412
+ @waiting_fibers.each do |e|
1413
+ e.set_awake
1414
+ end
1415
+ @fiber = nil
1416
+ end
1417
+ end
1418
+ def set_semi_lock_fiber fiber
1419
+ @semi_lock_fibers[fiber] += 1
1420
+ end
1421
+ def reset_semi_lock_fiber fiber
1422
+ if @semi_lock_fibers.key? fiber
1423
+ tmp = (@semi_lock_fibers[fiber] -= 1)
1424
+ if tmp <= 0
1425
+ @semi_lock_fibers.delete fiber
1426
+ end
1427
+ end
1428
+ end
1429
+ def has_semi_lock_fiber fiber
1430
+ @semi_lock_fibers.key? fiber
1431
+ end
1432
+ public
1433
+ def synchronize mode = :normal, &prc
1434
+ Fiber.current.mutexSync self, mode, &prc
1435
+ end
1436
+ end
1437
+ friend Mutex
1438
+ #private
1439
+ def mutexSyncLock
1440
+ mutex = @mutexStack[-1]
1441
+ if !@lockStat[-1]
1442
+ @lockStat[-1] = true
1443
+ mutex.lock self
1444
+ end
1445
+ end
1446
+ def mutexSyncUnlock
1447
+ mutex = @mutexStack[-1]
1448
+ mutex.unlock self
1449
+ end
1450
+ def mutexSync mutex, mode
1451
+ res = nil
1452
+ begin
1453
+ @mutexList[mutex] += 1
1454
+ @mutexStack.push mutex
1455
+ @lockStat.push false
1456
+ case mode
1457
+ when :semi
1458
+ mutex.set_semi_lock_fiber self
1459
+ else
1460
+ mutexSyncLock
1461
+ end
1462
+ begin
1463
+ res = yield
1464
+ ensure
1465
+ mutexSyncUnlock
1466
+ end
1467
+ ensure
1468
+ tmp = (@mutexList[mutex] -= 1)
1469
+ if tmp == 0
1470
+ @mutexList.delete mutex
1471
+ end
1472
+ @mutexStack.pop
1473
+ @lockStat.pop
1474
+ res
1475
+ end
1476
+ end
1477
+
1478
+ # STDIN = Fiber.new ::STDIN
1479
+ # STDOUT = Fiber.new ::STDOUT
1480
+ # STDERR = Fiber.new ::STDOUT
1481
+ # def tmode= m
1482
+ # @mode = m
1483
+ # end
1484
+ # def tmode
1485
+ # @mode
1486
+ # end
1487
+
1488
+ at_exit do
1489
+ p :cyan, $!
1490
+ if $! && !$!.is_a?(SystemExit)
1491
+ # $!.instance_eval {
1492
+ # STDERR.write "#{backtrace[0]}:#{$!} (#{self.class})".ln
1493
+ # backtrace[1..-1].each do |e|
1494
+ # STDERR.write " " + e.ln
1495
+ # end
1496
+ # }
1497
+ @aborted = true
1498
+ # abort
1499
+ end
1500
+ p Fiber::List.size
1501
+ toTerm = []
1502
+ Fiber::List.each do |t, fibers|
1503
+ fibers.each do |fiber|
1504
+ if fiber.auto_cleanup?
1505
+ toTerm.push fiber
1506
+ end
1507
+ end
1508
+ end
1509
+ p toTerm
1510
+ p Fiber::List.size
1511
+ toTerm.each &:terminate
1512
+ p Fiber::List.size
1513
+ if !@aborted && Fiber::List.size > 1
1514
+ p Fiber::List
1515
+ raise Exception.new("#{Fiber::List.size - 1} Fiber procedure(s) not cleaned")
1516
+ end
1517
+ p
1518
+ end
1519
+ end
1520
+
1521
+ Fiber.current.set_params :start
1522
+
1523
+
1524
+