YkLib 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+